package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap;

import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.common.WarehousePilotService;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.dto.OrderDetailConfirmQuantityResp;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.innerService.FulfillmentOrderService;
import com.alibaba.cirtus.ots.application.adapter.ability.model.api.*;
import com.alibaba.cirtus.ots.application.adapter.ability.model.enums.MnSAPStatus;
import com.alibaba.cirtus.ots.application.adapter.ability.model.request.AllocateOrderSalesOrderSyncRequest;
import com.alibaba.cirtus.ots.application.adapter.ability.model.response.*;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.*;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.exception.ProcessException;
import com.alibaba.citrus.ots.common.util.JsonUtil;
import com.alibaba.citrus.ots.common.util.SapAndCrmFieldDealUtils;
import com.alibaba.citrus.ots.common.util.TimeUtil;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.ScItemSDO;
import com.epoch.app.bcorder.model.dto.*;
import com.epoch.app.bcorder.platform_enhance.SaleOrderTag;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.UnifiedInventoryService;
import com.epoch.app.bcots.contants.BcOtsConstants;
import com.epoch.app.crb2btradecenter.api.orderwrite.service.OrderWriteService;
import com.epoch.app.crb2btradecenter.domain.order.dto.LoadOrderListRequest;
import com.epoch.app.crb2btradecenter.domain.order.dto.UpdateOrderResponse;
import com.epoch.app.crb2btradecenter.domain.order.model.Order;
import com.epoch.app.crb2btradecenter.domain.order.service.OrderService;
import com.epoch.app.crb2btradecenter.domain.orderline.dto.QuerySalesOrderLineByIdsRequest;
import com.epoch.app.crb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.crb2btradecenter.domain.orderline.service.OrderLineService;
import com.epoch.app.crb2btradecenter.dto.request.ModifyOrderLineRequest;
import com.epoch.app.crb2btradecenter.dto.request.ModifyOrderRequest;
import com.epoch.app.crforecastsales.api.forecastorderlinequery.service.ForecastOrderLineQueryService;
import com.epoch.app.crforecastsales.model.dto.QuerySaleUnitRequest;
import com.epoch.app.crforecastsales.model.dto.SelectCombox;
import com.epoch.app.crplatformenhance.api.group.scitemgroupquery.service.ScItemGroupQueryService;
import com.epoch.app.crplatformenhance.api.organizationquery.service.OrganizationQueryService;
import com.epoch.app.crplatformenhance.dto.request.IdQueryRequest;
import com.epoch.app.crplatformenhance.dto.request.QueryScItemGroupRequest;
import com.epoch.app.crplatformenhance.dto.response.ScItemGroupResponse;
import com.epoch.app.crplatformenhance.interfacedatasyncconfigquery.service.InterfaceDataSyncConfigQueryService;
import com.epoch.app.crplatformenhance.model.dto.*;
import com.epoch.app.crplatformenhance.model.enums.OrderTypeEnum;
import com.epoch.app.crplatformenhance.sdo.CustomerAddressSDO;
import com.epoch.app.crplatformenhance.service.CrPlatformEnhanceService;
import com.epoch.app.crpricecenter.api.creditquery.service.CreditQueryService;
import com.epoch.app.crpricecenter.model.dto.CreditInfoSDO;
import com.epoch.app.crpricecenter.model.dto.CreditQueryRequest;
import com.epoch.app.crunifiedinventory.api.allocateorderwrite.service.AllocateOrderWriteService;
import com.epoch.app.crunifiedinventory.api.forecastwarehouse.dto.QueryWarehouseByFactoryCodeAndWarehouseCodeRequest;
import com.epoch.app.crunifiedinventory.api.forecastwarehouse.service.ForecastWarehouseService;
import com.epoch.app.crunifiedinventory.dto.response.AllocateOrderSalesOrderSyncResponse;
import com.epoch.app.crunifiedinventory.model.dto.WarehouseInfoDTO;
import com.epoch.app.otsapplicationadaptersdk.contants.OtsApplicationAdapterSdkConstants;
import com.epoch.app.otsapplicationadaptersdk.materialsyncretry.model.MaterialSyncRetry;
import com.epoch.app.otsapplicationadaptersdk.materialsyncretry.service.MaterialSyncRetryService;
import com.epoch.app.otsapplicationadaptersdk.model.dto.*;
import com.epoch.app.otsapplicationadaptersdk.model.enums.RetryStatus;
import com.epoch.app.otsapplicationadaptersdk.model.enums.SapApiCode;
import com.epoch.app.otsapplicationadaptersdk.sap.*;
import com.epoch.app.otsapplicationadaptersdk.sapretrywrite.service.SapRetryWriteService;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif004v2.service.MnSapIf004V2Service;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif013v2.service.MnSapIf013V2Service;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif015v2.service.MnSapIf015V2Service;
import com.epoch.app.otsapplicationadaptersdk.service.OtsApplicationAdapterSdkService;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.AtomicDouble;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * @author: yuhw
 * @description: sap请求平台销售单更改，销售订单 退单 更新接口 F-B F-b
 * @date: 2021年09月27日 21:26
 **/
@Component
@Primary
public class MnSapIf013V2ServiceImpl implements MnSapIf013V2Service {
    private final Log log = Log.getLogger(MnSapIf013V2ServiceImpl.class);
    
    @Autowired
    private AllocateOrderWriteService allocateOrderWriteService;
    @Autowired
    private UnifiedInventoryService unifiedInventoryService;
    @Resource
    private ForecastWarehouseService forecastWarehouseService;
    @Resource
    CrPlatformEnhanceService otsPlatformEnhanceService;
    @Autowired
    private OrderWriteService orderWriteService;
    @Autowired
    private BaseDataService baseDataService;
    @Autowired
    private ScItemGroupQueryService scItemGroupQueryService;
    @Autowired
    private ForecastOrderLineQueryService forecastOrderLineQueryService;
    @Autowired
    private CreditQueryService creditQueryService;
    @Autowired
    private OrganizationQueryService organizationQueryService;
    @Autowired
    private InterfaceDataSyncConfigQueryService interfaceDataSyncConfigQueryService;
    @Resource
    private SapRetryWriteService sapRetryWriteService;
    @Resource
    private MaterialSyncRetryService materialSyncRetryService;
    @Resource(type = MnSapIf004V2ServiceImpl.class)
    private MnSapIf004V2Service mnSapIf004V2Service;
    @Resource(type = MnSapIf015V2Service.class)
    private MnSapIf015V2Service mnSapIf015V2Service;
    @Resource
    private WarehousePilotService warehousePilotService;
    @Resource
    private OrderLineService orderLineService;
    @Resource
    private OrderService orderService;
    @Resource
    private OutOpenapiHttpUtils outOpenapiHttpUtils;
    @Resource
    private OtsApplicationAdapterSdkService otsApplicationAdapterSdkService;
    @Resource
    private EpochMessageService messageService;
    @Resource
    private EpochCacheService epochCacheService;
    @Autowired
    private HttpUtils httpUtils;
    @Resource
    private FulfillmentOrderService fulfillmentOrderService;
    @Value("${ots.checkTimestamp:0}")
    private boolean checkTimestamp;
    private static final Integer MAX_PAGE_SIZE = 1000;
    private static final String ORG_CODE = "1171";
    private static final String SIX_THOUSAND_ORG_ID = "286072177888956796";
    private static final String CREATE_ORDER_URL = "/delivery/dubbo/api/fulfillment/createOrder";
    private static final String SEARCH_ORDER_URL = "/delivery/dubbo/api/fulfillment/searchList";
    private static final String CLOSE_ORDER_URL = "/delivery/dubbo/api/fulfillment/finish";
    private static final Long SAP_TIMESTAMP_CACHE_EXPIRE = 60 * 60 * 24 * 100L;
    @Override
    @ProcessInvoker(remark = "MnSapIf013V2Service", errorCode = "OTS-02-007-00-16-999", printLog = true)
    public MnSapCommResponse externalUpdateAllocateBySaleOrder(MnSapIf013Request mnSapIf013Request) {
        log.info("MnSapIf013V2Service sap013 MnSapIf013ServiceImpl externalUpdateAllocateBySaleOrder request:{}",JSON.toJSONString(mnSapIf013Request));

        //F-B 销售订单明细回传也用013接口，需先判断是不是一盘货F-B订单，如果是F-B订单，则走订单流程；如果不是F-B订单，则走老的调拨单流程
        if (CollectionUtils.isEmpty(mnSapIf013Request.getData())) {
            return ResponseUtil.fail(mnSapIf013Request,"传递的调拨单参数列表为空");
        }
        MnSapCommResponse response = new MnSapCommResponse();
        List<MnSapCommSDO> mnSapCommSDOS = Lists.newArrayList();
        MessageHeaderSDO messageHeader = mnSapIf013Request.getMessageHeader();
        for (MnSapIf013SDO sdo : mnSapIf013Request.getData()){
            //根据发货仓(根据工厂编码+库存地点找到逻辑仓，根据逻辑仓判断是否在试点范围内)判断是否是一盘货F-B销售订单
            //如果是一盘货F-B销售订单，则走销售订单更新逻辑
            QueryWarehouseByFactoryCodeAndWarehouseCodeRequest wareHouseQueryRequest = new QueryWarehouseByFactoryCodeAndWarehouseCodeRequest();
            wareHouseQueryRequest.setWarehouseCode(sdo.getInventoryCode());
            wareHouseQueryRequest.setFactoryCode(sdo.getFactoryCode());
            log.info("MnSapIf013ServiceImpl.queryWarehouseByFactoryCodeAndWarehouseCode.ship.request:{}",JSON.toJSONString(wareHouseQueryRequest));
            Result<List<WarehouseInfoDTO>> queryWareHouseResult = forecastWarehouseService.queryWarehouseByFactoryCodeAndWarehouseCode(wareHouseQueryRequest);
            log.info("MnSapIf013ServiceImpl.queryWarehouseByFactoryCodeAndWarehouseCode.ship.result:{}",JSON.toJSONString(queryWareHouseResult));
            if (Objects.isNull(queryWareHouseResult)|| !queryWareHouseResult.isSuccess() || CollectionUtils.isEmpty(queryWareHouseResult.getResult())) {
                return ResponseUtil.fail(mnSapIf013Request,"交货工厂和库存地点查询不到对应的发货仓");
            } else {
                WarehouseInfoDTO warehouseInfoDTO = queryWareHouseResult.getResult().get(0);
                //log.info("check if warehouse is  pilot,warehouseInfoDTO :{}", JSON.toJSONString(warehouseInfoDTO));
                boolean isPilot = warehousePilotService.isInPilotScope(warehouseInfoDTO.getCode());
                // 分子公司客户编码
                String[] customerCode = {"1900000821","1900008241","1900036869","1900024235","1900000816","1900037741","1900008539","1900024582","1900035757","1900000001","1965000119","1900000827","1900008263","1900001227","1900021273","1900027440","1900039345","1900000801","1900000803","1900000826","1900029519","1900000822","1900000814","1900000813","1900023074","1900000825","1900043735","1900038445","1900000800","1900008664","1900008459","1900035293","1900000799","1900000812","1900004400","1900029687","1900000806","1900000093","1900008535","1900000807","1900000824","1900009463","1900022946","1900035437","1900019218","1900000805","1900000810","1900000818","1900008362","1900008915","1900000819"};
                List<String> customerCodeList = Arrays.asList(customerCode);
                // 走OTW流程的工厂
                List<String> toOtwFactoryCodes = Lists.newArrayList("H025");
                // 试点范围内的工厂
                List<String> inPilotFactoryCodes = Lists.newArrayList( "H022");
                if (isPilot || toOtwFactoryCodes.contains(sdo.getFactoryCode())
                    || (inPilotFactoryCodes.contains(sdo.getFactoryCode()) && !customerCodeList.contains(sdo.getSoldPartCode()))) {

                    OrderAndDetailResponse orderAndDetail = getOrderAndDetail(sdo);

                    //参数转换,调mnSapIf015V2Service.externalSyncSaleOrder 复用B-b销售订单明细回传接口
                    MnSapIf015Request mnSapIf015Request = generateMnSapIf015Request(messageHeader, sdo,isPilot,toOtwFactoryCodes);
                    log.info("013 inner call 015,param:{}", JSON.toJSONString(mnSapIf015Request));
                    MnSapCommResponse mnSapCommResponse = mnSapIf015V2Service.externalSyncSaleOrder(mnSapIf015Request);
                    mnSapCommSDOS.addAll(mnSapCommResponse.getData());
                    //增加逻辑，针对sap修改订单明细的数量，主要是关闭现有履约单、补充新的履约单
//                    handleSapUpdateAmount(sdo,orderAndDetail);
                    try {
                        if (orderAndDetail != null) {
                            ifExistUpdateConfirmQuantityUnlock(orderAndDetail, sdo);
                            log.info("MnSapIf013ServiceImpl mnSapCommResponse ={}", JSON.toJSONString(mnSapCommResponse));
                            if (CollectionUtils.isNotEmpty(mnSapCommResponse.getData()) && !Objects.equals("49", mnSapCommResponse.getData().get(0).getErrCode())) {
                                handleSapUpdateAmountByMq(sdo, orderAndDetail);
                                //检查时间戳，乱序问题导致的旧的回调不做处理
                                handleConfirmQuantity(sdo, orderAndDetail, isPilot);
                            }
                        }else {
                            //针对SAP新增的销售订单的情况
                            if (CollectionUtils.isNotEmpty(mnSapCommResponse.getData()) && !Objects.equals("49",mnSapCommResponse.getData().get(0).getErrCode())){
                                orderAndDetail = getOrderAndDetail(sdo);
                                log.info("MnSapIf013ServiceImpl insert after orderAndDetail",JSON.toJSONString(orderAndDetail));
                                //检查时间戳，乱序问题导致的旧的回调不做处理
                                handleConfirmQuantity(sdo,orderAndDetail,isPilot);
                            }
                        }
                    }catch (Exception e){
                        log.error("MnSapIf013ServiceImpl sync confirm quantity error",e);
                    }

                } else {
                    //如果不是一盘货F-B销售订单，则走老的调拨单逻辑

                    //处理送达方和售达方前置0
                    sdo.setDeliveryPartCode(SapAndCrmFieldDealUtils.generateIdField(sdo.getDeliveryPartCode()));
                    sdo.setSoldPartCode(SapAndCrmFieldDealUtils.generateIdField(sdo.getSoldPartCode()));

                    //电商订单逻辑
                    if (ORG_CODE.equals(sdo.getSaleOrganizationCode())) {
                        if (SaleOrderTag.DS_STD_ORDER.getCode().equals(sdo.getOrderType())
                                || SaleOrderTag.DS_ZD_ORDER.getCode().equals(sdo.getOrderType())
                                || SaleOrderTag.DS_STD_RETURN_ORDER.getCode().equals(sdo.getOrderType())) {

                            MnSapCommResponse mnSapCommResponse = mnSapCommResponseConverter(mnSapIf013Request,sdo, response, mnSapCommSDOS);
                            //判断是否需要重试 需要则加入重试表
                            isNeedSaveRetry(mnSapCommResponse,mnSapIf013Request);
                            return mnSapCommResponse;
                        }
                    }


                    AllocateOrderSalesOrderSyncRequest request = new AllocateOrderSalesOrderSyncRequest();
                    request.setCode(sdo.getAllocateOrderId());
                    request.setOutAllocateApplyOrderId(sdo.getOutAllocateApplyOrderId());
                    request.setOutAllocateOrderId(sdo.getOutAllocateOrderId());
                    request.setOrderType(sdo.getOrderType());
                    if ("ZRE".equals(sdo.getOrderType())){
                        request.setReturnOrder(true);
                    }else {
                        request.setReturnOrder(false);
                    }
                    request.setSaleOrganizationCode(sdo.getSaleOrganizationCode());
                    // 组织转换
//            BaselineGetOrganizationByOutCodesRequest baselineGetOrganizationByOutCodesRequest = new BaselineGetOrganizationByOutCodesRequest();
//            baselineGetOrganizationByOutCodesRequest.setOutCodes(Lists.newArrayList(sdo.getSaleOrganizationCode()));
//            baselineGetOrganizationByOutCodesRequest.setStatus(1);
//            Map organizationMap = this.externalUpdateAllocateBySaleOrder$callAPI2(baselineGetOrganizationByOutCodesRequest);
//            String orgId = getOrgId(organizationMap);
//            // TODO 把获取预报单的请求下沉到预报单.
//            request.setApplyOrgId(orgId);

                    request.setSaleChannel(sdo.getSaleChannel());
                    request.setSaleDepartmentCode(sdo.getSaleDepartmentCode());

                    // 产品组
                    request.setProductGroup(sdo.getProductGroupCode());
                    request.setSaleChannel(sdo.getSaleChannel());
                    request.setSaleDepartmentCode(sdo.getSaleDepartmentCode());
                    //TODO 通过售达方编码,读取客户主数据中客户的"销售办公室"字段信息
                    request.setSapSalesOrgId(sdo.getSaleOrganizationCode());
                    //createTime 是时分秒  年月日 在createDate上
                    if (StringUtils.isNotBlank(sdo.getCreateDate())){
                        if (StringUtils.isNotBlank(sdo.getCreateTime())){
                            request.setCreateTime(TimeUtil.parseYYYYMMddHHmmss(sdo.getCreateDate() + sdo.getCreateTime()));
                        }else {
                            request.setCreateTime(TimeUtil.parseSimpleDateFormat(sdo.getCreateDate()));
                        }
                    }
//            request.setCreateTime(TimeUtil.parseSimpleDateFormat(sdo.getCreateTime()));
                    request.setUpdateTime(TimeUtil.parseSimpleDateFormat(sdo.getModifyDate()));

//            request.setGmtModified(TimeUtil.parseSimpleDateFormat(sdo.getModifyDate()));
//            request.setModifyTime(TimeUtil.parseSimpleDateFormat(sdo.getModifyDate()));
                    request.setDocDate(TimeUtil.parseSimpleDateFormat(sdo.getDocTime()));
                    //TODO 看情况需要转换 产品组 工厂 库位 算了 从 预报单上取好了.
                    QueryWarehouseByFactoryCodeAndWarehouseCodeRequest queryRequest = new QueryWarehouseByFactoryCodeAndWarehouseCodeRequest();
                    queryRequest.setWarehouseCode(sdo.getInventoryCode());
                    queryRequest.setFactoryCode(sdo.getFactoryCode());
                    log.info("MnSapIf013ServiceImpl.queryWarehouseByFactoryCodeAndWarehouseCode.ship.request:{}",JSON.toJSONString(queryRequest));

                    Result<List<WarehouseInfoDTO>> listResult = forecastWarehouseService.queryWarehouseByFactoryCodeAndWarehouseCode(queryRequest);
                    log.info("MnSapIf013ServiceImpl.queryWarehouseByFactoryCodeAndWarehouseCode.ship.result:{}",JSON.toJSONString(listResult));

//            WmsQueryWarehouseZoneListRequest zoneListRequest = new WmsQueryWarehouseZoneListRequest();
//            if (StringUtils.isNotEmpty(sdo.getInventoryCode())){
//                zoneListRequest.setWarehouseCode(sdo.getInventoryCode());
//            }else {
//                zoneListRequest.setWarehouseCode("DEFAULT");
//            }
//            zoneListRequest.setSapFactoryCode(sdo.getFactoryCode());
//            WmsQueryWarehouseZoneListResponse shipResponse = unifiedInventoryService.wmsQueryWarehouseZoneList(zoneListRequest);
                    String shipAreaId = getAreaId(listResult);
                    if (StringUtils.isBlank(shipAreaId)){
                        log.info("MnSapIf013ServiceImpl.queryWarehouseByFactoryCodeAndWarehouseCode.ship.error:{}",JSON.toJSONString(listResult));
                        return ResponseUtil.fail(mnSapIf013Request,"交货工厂和库存地点查询不到对应的发货仓");
                    }
                    String shipWarehouseId = getWarehouseId(listResult);
                    request.setShipAreaId(shipAreaId);
                    request.setShipWarehouseId(shipWarehouseId);

                    // TODO 收货仓 从原单据上取 收货仓 和客户
                    //根据售达方和送达方查找仓库信息，查出多个返回错误，如果有值 取销售组织
                    SearchCargoZoneListRequest searchCargoZoneListRequest = new SearchCargoZoneListRequest();
                    searchCargoZoneListRequest.setSapSaleBPCode(sdo.getSoldPartCode());
                    //售达方
                    searchCargoZoneListRequest.setSapDeliveryBPCode(sdo.getDeliveryPartCode());
                    log.info("根据售达方和送达方查找仓库信息入参：售达方：{},送达方:{}",sdo.getSoldPartCode(),sdo.getDeliveryPartCode());
                    log.info("MnSapIf013ServiceImpl.searchCargoZoneList.receive.request:{}",JSON.toJSONString(searchCargoZoneListRequest));
                    SearchCargoZoneListResponse searchCargoZoneListResponse = unifiedInventoryService.searchCargoZoneList(searchCargoZoneListRequest);
                    log.info("MnSapIf013ServiceImpl.searchCargoZoneList.receive.result:{}",JSON.toJSONString(searchCargoZoneListResponse));

                    log.info("根据总部售达方和总部送达方查找仓库信息出参：", JSON.toJSONString(searchCargoZoneListResponse));
                    String receiveAreaId = null;
                    String receiveOrgId = null;
                    String orgOutCode = "";
                    Boolean isDTC = null;
                    String addressCode = null;
                    if (searchCargoZoneListResponse != null && CollectionUtils.isNotEmpty(searchCargoZoneListResponse.getResult())
                            && searchCargoZoneListResponse.getResult().size() == 1){
                        WarehouseInfo warehouseInfo = searchCargoZoneListResponse.getResult().get(0);
                        receiveAreaId = warehouseInfo.getId();
                        receiveOrgId = warehouseInfo.getSaleOrgId();
                    }else {
                        if (searchCargoZoneListResponse != null && CollectionUtils.isNotEmpty(searchCargoZoneListResponse.getResult())){
                            log.info("MnSapIf013ServiceImpl.searchCargoZoneList.receive.error:{}",JSON.toJSONString(searchCargoZoneListResponse));
                            return ResponseUtil.fail(mnSapIf013Request,"售达方或送达方有误，请重新填写");
                        }else {
                            //查找客户 和 客户编码
                            BatchQueryAddress2Request batchQueryAddress2Request = new BatchQueryAddress2Request();
                            batchQueryAddress2Request.setAddressCodes(Lists.newArrayList(sdo.getDeliveryPartCode()));
                            log.info("MnSapIf013ServiceImpl.searchCargoZoneList.batchQueryAddress2.request:{}",JSON.toJSONString(batchQueryAddress2Request));
                            BatchQueryAddress2Response batchQueryAddress2Response = otsPlatformEnhanceService.batchQueryAddress2(batchQueryAddress2Request);
                            log.info("MnSapIf013ServiceImpl.searchCargoZoneList.batchQueryAddress2.result:{}",JSON.toJSONString(batchQueryAddress2Response));
                            if (batchQueryAddress2Response != null && CollectionUtils.isNotEmpty(batchQueryAddress2Response.getResult())){
                                isDTC = true;
                                receiveOrgId = batchQueryAddress2Response.getResult().get(0).getOrgSaleOrganizationCode();

                                orgOutCode = getOrgOutCodeBySoldPartCode(sdo.getSoldPartCode());
                                addressCode = batchQueryAddress2Response.getResult().get(0).getId();
                            }else {
                                log.info("MnSapIf013ServiceImpl.searchCargoZoneList.batchQueryAddress2.error:{}",JSON.toJSONString(batchQueryAddress2Response));
                                return ResponseUtil.fail(mnSapIf013Request,"售达方或送达方有误，请重新填写");
                            }
                        }
                    }
                    try {
                        //根据配置表进行数据拦截过滤
                        DataCheckRequest dataCheckRequest = new DataCheckRequest();
                        dataCheckRequest.setOrderType(OrderTypeEnum.ALLOCATEORDER.getCode());
                        dataCheckRequest.setOrgOutCode(getOrgCode(receiveOrgId));
                        dataCheckRequest.setVariable(SapAndCrmFieldDealUtils.toDateString(sdo.getCreateDate()));
                        Result<Boolean> checkResult = interfaceDataSyncConfigQueryService.dataCheck(dataCheckRequest);
                        if (checkResult != null && checkResult.getResult() != null && !checkResult.getResult()){
                            log.info("013.interfaceDataSyncConfigQueryService 拦截 "+JSONObject.toJSONString(sdo));
                            MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                            mnSapCommSDO.setHeaderKey(sdo.getHeaderKey());
                            mnSapCommSDO.setStatus(MnSAPStatus.SUCCESS.getCode());
                            mnSapCommSDO.setMessage("成功！");
                            response.setData(Lists.newArrayList(mnSapCommSDO));
                            return success(mnSapIf013Request);
                        }
                    } catch (Throwable e) {
                        log.error("013.interfaceDataSyncConfigQueryService.Error", e);
                    }

                    request.setReceiveAreaId(receiveAreaId);
                    request.setReceiveOrgId(StringUtils.isNotBlank(orgOutCode)?orgOutCode:receiveOrgId);
                    request.setAddressCode(addressCode);
                    request.setIsDTC(isDTC);



                    //收货仓不修改
//            request.setReceiveWarehouseId(sdo.getFactoryCode());
//            request.setReceiveAreaId(sdo.getInventoryCode());
                    request.setExpectedDeliveryDate(TimeUtil.parseSimpleDateFormat(sdo.getExpectedDeliveryTime()));
                    request.setShipMethod(StringUtils.isNotBlank(sdo.getShipType())?Integer.parseInt(sdo.getShipType()):
                            null);
                    request.setRemark(sdo.getRemark());
                    request.setSapRefPoNo(sdo.getCustomerReferenceNo());
                    request.setSapCostCenter(sdo.getCostCenter());
                    request.setOrderReason(sdo.getOrderReason());
                    request.setFeatures(sdo.getFeatures());
                    request.setDocDate(TimeUtil.parseSimpleDateFormat(sdo.getDocTime()));
                    request.setSaleOrganizationCode(sdo.getSaleOrganizationCode());
                    request.setSapChannel(sdo.getSapChannel());
                    request.setSapSalesOrgId(sdo.getSaleOrganizationCode());
                    //设置下发时间
                    request.setExt(sdo.getExt());
                    //sap信贷检查
                    request.setExt1(sdo.getExt1());
                    List<MnSapIf013Detail> details = sdo.getItems();
                    List<AllocateOrderScItemDetailDTO> scItemDetails = Lists.newArrayList();
                    if (CollectionUtils.isNotEmpty(details)){
                        for (MnSapIf013Detail detail : details){
                            AllocateOrderScItemDetailDTO scItemDetail = new AllocateOrderScItemDetailDTO();
                            scItemDetail.setLineNo(detail.getAllocateOrderLineId());
                            scItemDetail.setOutAllocateApplyOrderLineId(detail.getOutAllocateApplyOrderLineId());
                            scItemDetail.setOutAllocateOrderLineId(InfoUtil.deleteZeroPrefix(detail.getOutAllocateOrderLineId()));
//                    scItemDetail.setScItemCode(SapAndCrmFieldDealUtils.generateIdField(detail.getScItemId()));
                            scItemDetail.setScItemCode(subStringScItmCode(detail.getScItemId()));
//                    scItemDetail.setScItemId(SapAndCrmFieldDealUtils.generateIdField(detail.getScItemId()));
                            scItemDetail.setScItemId(subStringScItmCode(detail.getScItemId()));
                            scItemDetail.setQuantity(StringUtils.isBlank(detail.getQuantity())?null:detail.getQuantity().trim());
                            if (request.getReturnOrder()){
                                scItemDetail.setConfirmQuantity(StringUtils.isBlank(detail.getQuantity())?null:detail.getQuantity().trim());
                            }else {
                                scItemDetail.setConfirmQuantity(StringUtils.isBlank(detail.getConfirmQuantity())?null:detail.getConfirmQuantity().trim());
                            }
                            scItemDetail.setUnit(detail.getSaleUnit());
                            scItemDetail.setUnitPrice(detail.getPrice());
                            scItemDetail.setPrice(detail.getPrice());
                            scItemDetail.setSubTotalAmount(detail.getSubTotalAmount());
//                    scItemDetail.setAllocateApplyOrderLineId(detail.geta);
                            // 拒绝编码?
                            scItemDetail.setCloseCode(detail.getCloseCode());
                            scItemDetail.setClosedReason(detail.getCloseReason());
                            if (StringUtils.isNotBlank(detail.getCloseCode()) || StringUtils.isNotBlank(detail.getCloseReason())){
                                scItemDetail.setClosed(true);
                            }else {
                                scItemDetail.setClosed(false);
                            }
                            //设置预报单行号
                            scItemDetail.setAllocateApplyOrderLineId(detail.getOutAllocateApplyOrderLineId());
                            if (StringUtils.isNotBlank(sdo.getExpectedDeliveryTime())){
                                scItemDetail.setExpectedDeliveryDate(TimeUtil.parseSimpleDateFormat(sdo.getExpectedDeliveryTime()));
                            }

                            scItemDetail.setRemark(detail.getRemarks());
                            scItemDetail.setRemarks(detail.getRemarks());
                            scItemDetail.setGiftQuantity(detail.getGiftQuantity());
                            scItemDetail.setTaxRate(detail.getTaxRate());
                            scItemDetail.setFeatures(detail.getFeatures());
                            //20220327 给生产日期一个默认值
                            if (StringUtils.isBlank(detail.getExt()) || "00000000".equals(detail.getExt())){
                                scItemDetail.setExpectedProduceDate(TimeUtil.parseSimpleDateFormat("20000101"));
                            }else{
                                scItemDetail.setExpectedProduceDate(TimeUtil.parseSimpleDateFormat(detail.getExt()));
                            }
                            //2022.2.22 确认日期修改为sap传递的
                            if (StringUtils.isNotBlank(detail.getExt1())){
                                scItemDetail.setConfirmTime(TimeUtil.parseSimpleDateFormat(detail.getExt1()));
                            }
                            scItemDetails.add(scItemDetail);
                        }
                    }
                    request.setAllocateOrderScItemDetails(scItemDetails);
                    com.epoch.app.crunifiedinventory.dto.request.AllocateOrderSalesOrderSyncRequest syncRequest =
                            JsonUtil.convert(request,
                                    com.epoch.app.crunifiedinventory.dto.request.AllocateOrderSalesOrderSyncRequest.class);
                    log.info("MnSapIf013ServiceImpl.salesOrderSync.request:{}",JSON.toJSONString(syncRequest));
                    Result<AllocateOrderSalesOrderSyncResponse> resultMap =  allocateOrderWriteService.salesOrderSync(syncRequest);
                    log.info("MnSapIf013ServiceImpl.salesOrderSync.result:{}",JSON.toJSONString(resultMap));

                    String code = null;
                    if (resultMap != null && resultMap.getResult() != null){
                        code = resultMap.getResult().getCode();
                    }
                    MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                    mnSapCommSDO.setHeaderKey(sdo.getHeaderKey());
                    mnSapCommSDO.setExtId(code);
                    if (StringUtils.isNotBlank(code) && code.startsWith("STO")){
                        mnSapCommSDO.setMessage(MnSAPStatus.SUCCESS.getMsg());
                        mnSapCommSDO.setStatus(MnSAPStatus.SUCCESS.getCode());
                        retry(request.getOutAllocateOrderId(),true);
                    }else {
                        mnSapCommSDO.setMessage(code);
                        mnSapCommSDO.setStatus(MnSAPStatus.ERROR.getCode());
                        mnSapCommSDO.setExtId(null);
                        //写入重试队列
                        saveSapRetry(mnSapIf013Request,mnSapIf013Request.getData().get(0),code );
                    }
                    List<MnSapCommDetail> mnSapCommDetails = Lists.newArrayList();
                    if (CollectionUtils.isNotEmpty(sdo.getItems())){
                        String finalCode = code;
                        mnSapCommDetails = sdo.getItems().stream().map(m->{
                            MnSapCommDetail mnSapCommDetail = new MnSapCommDetail();
                            mnSapCommDetail.setItemKey(m.getItem_key());
                            if (StringUtils.isNotBlank(finalCode) && finalCode.startsWith("STO")){
                                mnSapCommDetail.setStatus(MnSAPStatus.SUCCESS.getCode());
                                mnSapCommDetail.setMessage(MnSAPStatus.SUCCESS.getMsg());
                            }else {
                                mnSapCommDetail.setStatus(MnSAPStatus.ERROR.getCode());
                                mnSapCommDetail.setMessage(finalCode);
                            }
                            return mnSapCommDetail;
                        }).collect(Collectors.toList());

                    }
                    mnSapCommSDO.setItem(mnSapCommDetails);
                    mnSapCommSDOS.add(mnSapCommSDO);
                }
            }
        }
        response.setData(mnSapCommSDOS);
        response.setInterfacePath(mnSapIf013Request.getMessageHeader().getInterfacePath());
        response.setMessageId(mnSapIf013Request.getMessageHeader().getMessageId());
        return response;
    }
    private boolean isF2B(Order order){
        String[] orderType = {"ZFOC","ZOR","ZOR8"};
        List<String> orderTypeList = Arrays.asList(orderType);
        return "200".equals(order.getOrderCategoryCode()) && orderTypeList.contains(order.getOrderType());
    }
    private void handleConfirmQuantity(MnSapIf013SDO sdo, OrderAndDetailResponse orderAndDetail, boolean isPilot) {
        if(Objects.isNull(orderAndDetail)){
            log.error("handleConfirmQuantity not find order,sdo={}",sdo.getOutAllocateOrderId());
            return;
        }
        if(!isPilot){
            return;
        }
        //只针对F-B的销售订单
        if(!isF2B(orderAndDetail.getOrder())){
            return;
        }
        //过滤掉不走OTW的F-B订单，采用履约方式判断 外仓发货大仓收货，外仓发货外仓收货 不进行047处理
        List<String> filterFulfillmentTypes = Arrays.asList("120", "130");

        if(filterFulfillmentTypes.contains(orderAndDetail.getOrder().getFulfillmentTypeCode())){
            return;
        }
        //只针对第一次013回调进行处理
        String redisKey = String.format("%s-%s", "confirmQuantitySyncFirstTime", sdo.getAllocateOrderId());
        String exist = epochCacheService.get(BcOtsConstants.REDIS_CACHE_CODE(), redisKey);
        if(StringUtils.isNotEmpty(exist)){
            //表示第一次回调 remove the key
            epochCacheService.remove(BcOtsConstants.REDIS_CACHE_CODE(), Lists.newArrayList(redisKey));
        }else{
            //如果不存在了，表示不是第一次回调
            return;
        }

        handleConfirmQuantitySyncSapByMq(sdo,orderAndDetail);

    }
    private void handleConfirmQuantitySyncSapByMq(MnSapIf013SDO sdo, OrderAndDetailResponse orderAndDetail) {

        SalesOrderConfirmQuantitySapEventMessage salesOrderSapEventMessage = new SalesOrderConfirmQuantitySapEventMessage();
        salesOrderSapEventMessage.setSdo(sdo);
        salesOrderSapEventMessage.setOrderNo(orderAndDetail.getOrder().getOrderBizId());
        salesOrderSapEventMessage.setBusinessType(orderAndDetail.getOrder().getBusinessType());
        salesOrderSapEventMessage.setFirstTime(System.currentTimeMillis());
        try{
            Boolean result = messageService.sendMessage("sales_order_confirm_quantity_first_sync", "CR_SALEORDER_V2", "SalesOrderConfirmQuantityFirst",
                    sdo.getOutAllocateOrderId(),JSONObject.toJSONString(salesOrderSapEventMessage));
            log.info("handleConfirmQuantitySyncSapByMq message={} result={}",JSON.toJSONString(salesOrderSapEventMessage),result);
        }catch (Exception e){
            log.error("handleConfirmQuantitySyncSapByMq error",e);
        }
    }

    private void ifExistUpdateConfirmQuantityUnlock(OrderAndDetailResponse orderAndDetail, MnSapIf013SDO sdo) {
        log.info("MnSapIf013V2Service ifExistUpdateConfirmQuantityUnlock orderAndDetail={},sdo={}",JSON.toJSONString(orderAndDetail),JSON.toJSONString(sdo));
        try {
            if(!isF2B(orderAndDetail.getOrder())){
                return;
            }
            List<OrderLine> orderLineList = orderAndDetail.getOrderLineList();
            Map<String, Integer> serialNumberMap = new HashMap<>();
            orderLineList.stream().forEach(it-> serialNumberMap.put(it.getSerialNumber(),it.getConfirmQuantity()));
            List<MnSapIf013Detail> items = sdo.getItems();
            boolean isUpdate = false;
            for (int i = 0; i < items.size(); i++) {
                MnSapIf013Detail mnSapIf013Detail = items.get(i);
                //前面有0000
                String scItemId = mnSapIf013Detail.getItem_key().replaceAll("^0*","");
                if(serialNumberMap.containsKey(scItemId)){
                    //这里可能会是null，表示还没有更新订单明细表
                    Integer confirmQuantity = serialNumberMap.get(scItemId);
                    //这里也可能是null，只有sap回调的数据有确认数量才做释放锁操作，因为这是履约单创建的时候，会同步给sap，刷新确认数量
                    if(StringUtils.isNotBlank(mnSapIf013Detail.getConfirmQuantity())){
                        if(!Objects.equals(Double.valueOf(mnSapIf013Detail.getConfirmQuantity()).intValue(),confirmQuantity)){
                            isUpdate  = true;
                            break;
                        }
                    }
                }
            }
            log.info("MnSapIf013V2Service ifExistUpdateConfirmQuantityUnlock orderBizId={} isUpdate= {}",orderAndDetail.getOrder().getOrderBizId(),isUpdate);
            if (isUpdate){
                String redisKey = String.format("%s-%s", "confirmQuantitySync", orderAndDetail.getOrder().getOrderBizId());
                unlock(redisKey);
            }
        }catch (Exception e){
            log.error("MnSapIf013V2Service ifExistUpdateConfirmQuantityUnlock error",e);
        }
    }

    private void unlock(String redisKey) {
        try {
            String s = epochCacheService.get(BcOtsConstants.REDIS_CACHE_CODE(), redisKey);
            log.info("013 unlock key={},is exist={}",redisKey,s);
            if (s == null){
                return;
            }
            boolean remove = epochCacheService.remove(BcOtsConstants.REDIS_CACHE_CODE(), Lists.newArrayList(redisKey));
            if (remove){
                log.info("MnSapIf013V2Service ThreadId="+Thread.currentThread().getId()+"|SaleRedis key="+redisKey+"|unlock");
            }
        }catch (Exception e ){
            log.error("MnSapIf013V2Service unlock error",e);
        }
    }

    /**
     * 如果订单明细的履约数量和确认数量存在差异，需要调用047接口同步给sap
     * @param orderDetailConfirmQuantityMap 订单明细的确定数量map
     * @param sdo sap回调的订单明细数据
     */
    private void ifExistDiffSendToSap(Map<String, String> orderDetailConfirmQuantityMap, MnSapIf013SDO sdo, OrderAndDetailResponse response,String fulfillmentOrderNo) {
        log.info("MnSapIf013V2Service ifExistDiffSendToSap orderDetailConfirmQuantityMap={}",JSON.toJSONString(orderDetailConfirmQuantityMap));
        List<MnSapIf013Detail> items = sdo.getItems();
        Map<String, String> scItemIdMap = new HashMap<>();
        items.forEach(it-> scItemIdMap.put(it.getItem_key().replaceAll("^0*",""),it.getConfirmQuantity()));
        Map<String,String> lineNoMap = new HashMap<>();
        scItemIdMap.forEach((key,value)->{
            if(orderDetailConfirmQuantityMap.containsKey(key)){
                String quantity = orderDetailConfirmQuantityMap.get(key);
                //如果sap发过来的确认数量是null,当作0.0处理
                String valueTemp  = StringUtils.isNotBlank(value) ? value:"0.0";
                Double diff = Double.parseDouble(quantity)-Double.parseDouble(valueTemp);
                if(diff!=0.0D){
                    lineNoMap.put(key,String.valueOf(diff));
                }
            }else{
                //如果没有履约数量就默认是0.0
                String valueTemp  = StringUtils.isNotBlank(value) ? value:"0.0";
                Double diff = Double.parseDouble("0.0")-Double.parseDouble(valueTemp);
                if(diff!=0.0D){
                    lineNoMap.put(key,String.valueOf(diff));
                }
            }
        });
        //构建参数发送047接口 TODO
        if(CollectionUtils.isNotEmpty(items)){
            RestAllocateOrderConfirmRequest request = new RestAllocateOrderConfirmRequest();
            JSONObject messageHeaderSDO = RequestUtils.generateMessageHeader("SI_ZT_AllocateConfirm_Asyn_OUT","YWZT","ECC","yyyyMMddHHmmss");
            request.setMessageHeader(messageHeaderSDO);
            request.setDocType("SO");
            request.setExt("");
            request.setExt1("");
            request.setExt2("");
            List<JSONObject> list = new ArrayList<>();
            items.stream().forEach(it->{
                JSONObject item = new JSONObject();
                String itemKey = it.getItem_key().replaceAll("^0*", "");
                if(lineNoMap.containsKey(itemKey)){
                    String diff = lineNoMap.get(itemKey);
                    item.put("diffConfirmQuantity",diff);
                    item.put("posnr",itemKey);
                    item.put("vbeln",sdo.getHeaderKey());
                    item.put("edatu","");
                    list.add(item);
                }else{
                    log.error("order detail lineNo={} not exist diff ",itemKey);
                }
            });
            if(CollectionUtils.isNotEmpty(list)){
                request.setItems(list);
                Map<String, Integer> orderLineConfirmQuantityMap = new HashMap<>();
                        response.getOrderLineList().stream().forEach(it->{
                            orderLineConfirmQuantityMap.put(it.getSerialNumber(),it.getConfirmQuantity());
                        });
                log.info("MnSapIf013V2ServiceImpl current order line confirm quantity={},sap confirm quantity={},delivery quantity={}",JSON.toJSONString(orderLineConfirmQuantityMap),JSON.toJSONString(scItemIdMap),JSON.toJSONString(orderDetailConfirmQuantityMap));
                log.info("ifExistDiffSendToSap request ={},",JSON.toJSONString(request));
                String redisKey = String.format("%s-%s", "confirmQuantitySync", response.getOrder().getOrderBizId());
                //按照正常情况，这里第一次调用047，履约单还没有生成，这里一定能获取锁
                boolean setnx = epochCacheService.setnx(BcOtsConstants.REDIS_CACHE_CODE(), redisKey, "1");
                if(setnx){
                    //过期时间，避免一直锁住，如果30分钟SAP都没有回来，那是他们的问题了
                    epochCacheService.expire(BcOtsConstants.REDIS_CACHE_CODE(),redisKey,30,TimeUnit.MINUTES);
                    log.info("MnSapIf013V2ServiceImpl ifExistDiffSendToSap redisKey {} obtain lock ready handle",redisKey);
                    Object result = otsApplicationAdapterSdkService.restAllocateOrderConfirm(request);
                    log.info("ifExistDiffSendToSap result ={},",JSON.toJSONString(result));
                    toBcLink(request, response.getOrder().getOrderBizId(),fulfillmentOrderNo,response.getOrder().getBusinessType());
                }else {
                    log.info("ifExistDiffSendToSap redisKey = {} not obtain lock",response.getOrder().getOrderBizId());
                }
            }
        }
    }

    private void toBcLink(RestAllocateOrderConfirmRequest request, String orderBizId, String fulfillmentOrderNo,Integer businessType) {
        log.info("MnSapIf013V2ServiceImpl toBcLink param:{}", JSON.toJSONString(request));
        try {
            Map<String, String> header = HttpTokenUtil.generateHttpHeader();
            String urlPrefix = OtsApplicationAdapterSdkConstants.urlPrefix();
            String url = urlPrefix + "api/mn_bc_link/saveTaskLog";

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("apiCode", "MN-SAP-IF-047");
            jsonObject.put("apiDesc", "中台确认数量同步SAP");
            jsonObject.put("callback", false);
            jsonObject.put("errorCode", "");
            jsonObject.put("errorMessage", "");
            jsonObject.put("executeStatus", 1);
            jsonObject.put("interfacePath", "MnSapIfSOModify$confirmQuantitySync");
            jsonObject.put("key", orderBizId);
            jsonObject.put("messageId", JSON.parseObject(JSON.toJSONString(request.getMessageHeader())).getString("messageId"));

            JSONObject retryParam = new JSONObject();
            JSONObject data = new JSONObject();
            data.put("businessType",businessType);
            data.put("orderNo",orderBizId);
            data.put("fulfillmentOrderNo",fulfillmentOrderNo);
            JSONObject message = new JSONObject();
            message.put("data", data);
            retryParam.put("message", message);

            jsonObject.put("retryParam", retryParam.toJSONString());
            jsonObject.put("requestInfo", JSON.toJSONString(request));
            jsonObject.put("sourceClient", "ZT");
            jsonObject.put("targetClient", "SAP");
            jsonObject.put("bizOrderId", orderBizId);

            log.info("MnSapIf013V2ServiceImpl toBcLink call bc link interface,url:{}, header:{}, " + "param:{}", url,
                header, jsonObject);
            ResponseEntity<com.alibaba.cirtus.ots.application.adapter.ability.model.Result> post = httpUtils.post(url, header, jsonObject,
                com.alibaba.cirtus.ots.application.adapter.ability.model.Result.class);
            com.alibaba.cirtus.ots.application.adapter.ability.model.Result result = post.getBody();
            log.info("MnSapIf013V2ServiceImpl toBcLink result:{}", JSON.toJSONString(result));
        } catch (Exception e) {
            log.error("MnSapIf013V2ServiceImpl toBcLink error", e);
        }
    }

    /**
     * 获取订单明细的履约数量，用于赋值给订单明细的确定数量
     * @return 订单明细的履约数量
     * @param response 订单数据
     */
    private OrderDetailConfirmQuantityResp getOrderDetailConfirmQuantity(OrderAndDetailResponse response) {
        OrderDetailConfirmQuantityResp resp = new OrderDetailConfirmQuantityResp();
        Map<String,String> map = new HashMap<>();
        List<BcFulfillmentOrderDetailSearchResponse> searchResponse = fulfillmentOrderService.getEffectiveBcFulfillmentOrderDetail(response.getOrder());
        if (CollectionUtils.isEmpty(searchResponse)){
            resp.setOrderDetailConfirmQuantityMap(map);
            return resp;
        }

        Map<String, List<BcFulfillmentOrderDetailSearchResponse>> lineNoMap = searchResponse.stream().collect(Collectors.groupingBy(BcFulfillmentOrderDetailSearchResponse::getLineNumber));
        lineNoMap.forEach((key,value)->{
            AtomicDouble atomicDouble = new AtomicDouble();
            value.stream().forEach(it->atomicDouble.addAndGet(Double.valueOf(it.getQuantity())));
            map.put(key,atomicDouble.toString());
        });
        resp.setOrderDetailConfirmQuantityMap(map);
        resp.setFulfillmentOrderNo(searchResponse.get(0).getFulfillmentOrderNo());
        return resp;
    }

    private void handleSapUpdateAmountByMq(MnSapIf013SDO sdo, OrderAndDetailResponse orderAndDetail) {
        if(!isF2B(orderAndDetail.getOrder())){
            return;
        }
        SalesOrderSapEventMessage salesOrderSapEventMessage = new SalesOrderSapEventMessage();
        salesOrderSapEventMessage.setSdo(sdo);
        salesOrderSapEventMessage.setOrderAndDetailResponse(orderAndDetail);
        try{
            Boolean result = messageService.sendMessage("consignment_order_message", "CR_SALEORDER_V2", "SalesOrderSapEvent",
                    sdo.getOutAllocateOrderId(),JSONObject.toJSONString(salesOrderSapEventMessage));
            log.info("handleSapUpdateAmountByMq#message={}#result={}",JSON.toJSONString(salesOrderSapEventMessage),result);
        }catch (Exception e){
            log.error("handleSapUpdateAmountByMq error",e);
        }
    }

    private OrderAndDetailResponse getOrderAndDetail(MnSapIf013SDO sdo) {
        OrderAndDetailResponse response= new OrderAndDetailResponse();
        log.info("MnSapIf013V2ServiceImpl#handleSapUpdateAmount#sdo={}",JSON.toJSONString(sdo));
        //查询中台的订单信息
        LoadOrderListRequest pageQueryRequest = new LoadOrderListRequest();
        if (StringUtils.isBlank(sdo.getAllocateOrderId())) {
            return null;
        }
        String id = sdo.getAllocateOrderId().replaceAll("^100", "");
        pageQueryRequest.setId(Long.valueOf(id));
        Result<List<Order>> loadOrderListResult = orderService.loadOrderList(pageQueryRequest);
        log.info("MnSapIf013V2ServiceImpl#handleSapUpdateAmount#loadOrderListResult={}",JSON.toJSONString(loadOrderListResult));
        if (Objects.isNull(loadOrderListResult) || CollectionUtils.isEmpty(loadOrderListResult.getResult())){
            return null;
        }
        Order order = loadOrderListResult.getResult().get(0);
        QuerySalesOrderLineByIdsRequest querySalesOrderLineByIdsRequest = new QuerySalesOrderLineByIdsRequest();
        //查询中台的订单明细信息
        querySalesOrderLineByIdsRequest.setMainOrderId(String.valueOf(order.getId()));
        Result<List<OrderLine>> listResult = orderLineService.querySalesOrderLineByIds(querySalesOrderLineByIdsRequest);
        log.info("MnSapIf013V2ServiceImpl#handleSapUpdateAmount#listResult={}",JSON.toJSONString(listResult));
        if(Objects.isNull(listResult) || CollectionUtils.isEmpty(listResult.getResult())){
            return null;
        }
        response.setOrder(order);
        response.setOrderLineList(listResult.getResult());
        return response;
    }

    private void handleSapUpdateAmount(MnSapIf013SDO sdo, OrderAndDetailResponse orderAndDetail) {
        if (Objects.isNull(orderAndDetail)){
            return;
        }
        List<OrderLine> orderLineList = orderAndDetail.getOrderLineList();
        Order order = orderAndDetail.getOrder();
        //是否修改了数量
        if(isModifyAmount(sdo,orderLineList)){
            try {
                doModifyAmount(order,orderLineList,sdo);
            }catch (Exception e ){
                log.error("handleSapUpdateAmount doModifyAmount error",e);
            }
        }
        //是否关闭了明细行
        if(isCloseLine(sdo)){
            try {
                doCloseLine(order,sdo);
            }catch (Exception e){
                log.error("handleSapUpdateAmount doCloseLine error",e);
            }
        }
        //是否修改了逻辑仓
        if(isModifyStock(sdo,orderLineList)){
            try{
                doModifyStock(order,sdo);
            }catch (Exception e){
                log.error("handleSapUpdateAmount doModifyStock error",e);
            }
        }
    }

    private void doModifyStock(Order order, MnSapIf013SDO sdo) {
        //查询履约单明细
        List<BcFulfillmentOrderDetailSearchResponse> searchResponse = fulfillmentOrderService.getBcFulfillmentOrderDetail(order);
        if (CollectionUtils.isEmpty(searchResponse)){
            //查询不到履约单，需要MQ异步处理，重试机制
//            messageService.sendMessage();
            return;
        }
        Map<String, List<BcFulfillmentOrderDetailSearchResponse>> detailListMap = searchResponse.stream().collect(Collectors.groupingBy(BcFulfillmentOrderDetailSearchResponse::getFulfillmentOrderNo));
        List<FinishReq.FulfillmentOrderInfo> list = Lists.newArrayList();
        detailListMap.forEach((key,value)->{
            //每一个主单都有明细，需要找出哪些需要关闭的，出库是基于明细行号的，如果出库单中某个明细行号已经全部出库了，就不需要关闭了
            for (int i = 0; i < value.size(); i++) {
                BcFulfillmentOrderDetailSearchResponse v = value.get(i);
                FinishReq.FulfillmentOrderInfo orderInfo = new FinishReq.FulfillmentOrderInfo();
                orderInfo.setFulfillmentOrderNo(key);
                orderInfo.setFulfillmentSubOrderNo(Integer.valueOf(v.getLineNumber()));
                orderInfo.setReason(v.getCloseReason());
                list.add(orderInfo);
            }
        });
        doFinish(list,order,sdo);
    }

    private void doCloseLine(Order order, MnSapIf013SDO sdo) {
        //查询履约单明细
        List<BcFulfillmentOrderDetailSearchResponse> searchResponse = fulfillmentOrderService.getBcFulfillmentOrderDetail(order);
        if (CollectionUtils.isEmpty(searchResponse)){
            //查询不到履约单，需要MQ异步处理，重试机制
//            messageService.sendMessage();
            return;
        }
        //关闭的订单明细行
        Map<String,MnSapIf013Detail> closeLineNoMap = sdo.getItems().stream().filter(it->StringUtils.isNotBlank(it.getCloseReason())).collect(Collectors.toMap(MnSapIf013Detail::getAllocateOrderLineId,Function.identity(),(p1,p2)->p2));

        Map<String, List<BcFulfillmentOrderDetailSearchResponse>> detailListMap = searchResponse.stream().collect(Collectors.groupingBy(BcFulfillmentOrderDetailSearchResponse::getFulfillmentOrderNo));
        List<FinishReq.FulfillmentOrderInfo> list = Lists.newArrayList();
        detailListMap.forEach((key,value)->{
            //每一个主单都有明细，需要找出哪些需要关闭的，出库是基于明细行号的，如果出库单中某个明细行号已经全部出库了，就不需要关闭了
            for (int i = 0; i < value.size(); i++) {
                BcFulfillmentOrderDetailSearchResponse v = value.get(i);
                if(!closeLineNoMap.containsKey(v.getLineNumber())){
                    continue;
                }
                MnSapIf013Detail mnSapIf013Detail = closeLineNoMap.get(v.getLineNumber());
                FinishReq.FulfillmentOrderInfo orderInfo = new FinishReq.FulfillmentOrderInfo();
                orderInfo.setFulfillmentOrderNo(key);
                orderInfo.setFulfillmentSubOrderNo(Integer.valueOf(v.getLineNumber()));
                orderInfo.setReason(mnSapIf013Detail.getCloseCode());
                list.add(orderInfo);
            }
        });
        doFinish(list,order,sdo);
    }

    /**
     * 先根据销售订单查询关联的出库单，累计算出明细行对应的累计出库创建数量，计算销售订单数量与累计出库创建数量的差值，如果等于0查询对应的履约单，将该销售订单明细行对应的履约单上履约数量改成累计出库创建数量；
     * 如果等于0查询对应的履约单，将该销售订单明细行对应的履约单上履约数量改成累计出库创建数量；
     * 如果大于0查询对应的履约单，将该销售订单明细行对应的履约单上履约数量改成累计出库创建数量，同时按照差值生成新的履约单，操作成功后按照SAP修改的数据修改销售订单数量。
     * @param order
     * @param orderLineList
     * @param sdo
     */
    private void doModifyAmount(Order order, List<OrderLine> orderLineList, MnSapIf013SDO sdo) {
        //查询履约单明细
        List<BcFulfillmentOrderDetailSearchResponse> searchResponse = fulfillmentOrderService.getBcFulfillmentOrderDetail(order);
        if (CollectionUtils.isEmpty(searchResponse)){
            //查询不到履约单，需要MQ异步处理，重试机制
//            messageService.sendMessage();
            return;
        }
        //查询出库单
        QueryWmsOrderByOtherOrderRequest queryWmsOrderByOtherOrderRequest = new QueryWmsOrderByOtherOrderRequest();
        queryWmsOrderByOtherOrderRequest.setBizOrderId(order.getOrderBizId());
        queryWmsOrderByOtherOrderRequest.setContainSubOrders(true);
        log.info("doModifyAmount 013 queryInOutBoundByDelivery request:{}", JSON.toJSONString(queryWmsOrderByOtherOrderRequest));
        Result<WarehousingOrderDTOResponse> result  = null;
        try{
            result = otsApplicationAdapterSdkService.queryWmsOrderByOtherOrder(queryWmsOrderByOtherOrderRequest);
            log.info("doModifyAmount 013 queryInOutBoundByDelivery response:{}", JSON.toJSONString(result));
        }catch (Exception e){
            log.error("queryInOutBoundByDelivery error",e);
        }

        List<WarehousingOrderDTO> warehousingOrders = new ArrayList<>();
        //基于明细行号累计出库创建数量
        Map<String,Long> lineNoMap=new HashMap<>();

        if(Objects.isNull(result) ||Objects.isNull(result.getResult())||CollectionUtils.isEmpty(result.getResult().getWarehousingOrders())){
            orderLineList.forEach(item->{
                lineNoMap.put(item.getSerialNumber(),0L);
            });
        }else {
            //出库单
            warehousingOrders = result.getResult().getWarehousingOrders();
            warehousingOrders.forEach(item->{
                //出入库明细
                List<WmsOrderDetailDTO> wmsSubOrders = item.getWmsOrderDetailList().stream().filter(it->"1".equals(it.getStatus()) || "2".equals(it.getStatus())).collect(Collectors.toList());
                //遍历明细行，基于明细行号做累加处理
                wmsSubOrders.forEach(detail->{
                    //如果存在了就累加，不存在就新增
                    if(lineNoMap.containsKey(detail.getBizSubOrderId())){
                        Long exist = lineNoMap.get(detail.getBizSubOrderId());
                        lineNoMap.put(detail.getBizSubOrderId(),detail.getGoodsQuantity()+exist);
                    }else {
                        lineNoMap.put(detail.getBizSubOrderId(),detail.getGoodsQuantity());
                    }
                });
            });
        }
        //订单明细的销售数量
        Map<String,Long> orderLineMap = new HashMap<>();
        orderLineList.forEach(item-> orderLineMap.put(item.getSerialNumber(),Long.valueOf(item.getQuantity())));
        //计算出哪些明细行号，没有出库完，还存在部分待出库的，这些待出库的就是需要重新生成履约单
        Map<String,Long> remainMap = new HashMap<>();
        orderLineMap.forEach((key,value)->{
            if (lineNoMap.containsKey(key)){
                //已经出库的数量
                Long outLineNo = lineNoMap.get(key);
                //剩余未出库的数量
                Long remain = value - outLineNo;
                if (remain>0){
                    remainMap.put(key,remain);
                }
            }else {
                remainMap.put(key,value);
            }
        });
        log.info("doModifyAmount remainMap={}",JSON.toJSONString(remainMap));
        //返回值是主子明细打平的状态,，需要按照主单分组
        Map<String, List<BcFulfillmentOrderDetailSearchResponse>> detailListMap = searchResponse.stream().collect(Collectors.groupingBy(BcFulfillmentOrderDetailSearchResponse::getFulfillmentOrderNo));
        List<FinishReq.FulfillmentOrderInfo> list = Lists.newArrayList();
        detailListMap.forEach((key,value)->{
            //每一个主单都有明细，需要找出哪些需要关闭的，出库是基于明细行号的，如果出库单中某个明细行号已经全部出库了，就不需要关闭了
            for (int i = 0; i < value.size(); i++) {
                BcFulfillmentOrderDetailSearchResponse v = value.get(i);
                if("8".equals(v.getDetailStatus())){
                    continue;
                }
                //履约单行号
                String lineNumber = v.getLineNumber();
                //如果这个履约单行号还存在待出货的，就需要关闭当前履约明细行
                if (remainMap.containsKey(lineNumber)){
                    FinishReq.FulfillmentOrderInfo orderInfo = new FinishReq.FulfillmentOrderInfo();
                    orderInfo.setFulfillmentOrderNo(key);
                    orderInfo.setFulfillmentSubOrderNo(Integer.valueOf(v.getLineNumber()));
                    orderInfo.setReason(v.getCloseReason());
                    list.add(orderInfo);
                }
            }
        });
        ResponseEntity<BcBatchCloseFulfillmentOrderOpenApiResponseResult> resultResponseEntity = doFinish(list, order, sdo);
        if (Objects.isNull(resultResponseEntity) || Objects.isNull(resultResponseEntity.getBody())){
            return;
        }
        BcBatchCloseFulfillmentOrderOpenApiResponseResult body = resultResponseEntity.getBody();
        if (!body.isSuccess()){
            handleFail(order,body);
            return;
        }
        if(!remainMap.isEmpty()){
            CreateFulfillmentOrderOpenApiReq apiReq = buildCreateFulfillmentOrderOpenApiReq(order,sdo,orderLineList,remainMap);
            //如果大于0需要创建新的履约单
            ResponseEntity<FulfillmentOrderOpenApiResponseResult> createResult = outOpenapiHttpUtils.post(CREATE_ORDER_URL, JSON.toJSON(apiReq), FulfillmentOrderOpenApiResponseResult.class);
            log.info("MnSapIf013V2ServiceImpl#doModifyAmount#createResult={}",JSON.toJSONString(createResult));
        }
    }

    private void handleFail(Order order, BcBatchCloseFulfillmentOrderOpenApiResponseResult body) {
        //如果失败了，需要记录信息到订单的bizFeatures
        String message = body.getMessage();
        String bizFeatures = order.getBizFeatures();
        Map<String,String> map = new HashMap<>();
        if (StringUtils.isNotBlank(bizFeatures)){
            map = JSON.parseObject(bizFeatures,Map.class);
        }
        map.put("msg",message);
        order.setBizFeatures(JSON.toJSONString(map));
        UpdateOrderResponse updateOrderResponse = orderService.updateOrder(order);
        log.info("MnSapIf013V2ServiceImpl handleFail response={}",JSON.toJSONString(updateOrderResponse));
    }

    private ResponseEntity<BcBatchCloseFulfillmentOrderOpenApiResponseResult> doFinish(List<FinishReq.FulfillmentOrderInfo> list,Order order, MnSapIf013SDO sdo){
        //构建批量关闭的请求参数
        FinishReq finishReq = new FinishReq();
        finishReq.setFulfillmentOrderInfoList(list);
        finishReq.setUpdater(sdo.getModifier());
        finishReq.setFromSys(order.getFromSys());
        finishReq.setBusinessType(String.valueOf(order.getBusinessType()));
        finishReq.setBusinessUnitCode(order.getBisUnitOutCode());
        //调用关闭接口
        ResponseEntity<BcBatchCloseFulfillmentOrderOpenApiResponseResult> outFinishResult = outOpenapiHttpUtils.post(CLOSE_ORDER_URL,JSON.toJSON(finishReq), BcBatchCloseFulfillmentOrderOpenApiResponseResult.class);
        log.info("MnSapIf013V2ServiceImpl#doModifyAmount#outFinishResult={}",JSON.toJSONString(outFinishResult));
        return outFinishResult;
    }


    private CreateFulfillmentOrderOpenApiReq buildCreateFulfillmentOrderOpenApiReq(Order order, MnSapIf013SDO sdo,List<OrderLine> orderLineList, Map<String, Long> remainMap) {
        CreateFulfillmentOrderOpenApiReq apiReq = new CreateFulfillmentOrderOpenApiReq();
        BeanUtils.copyProperties(order,apiReq);
        //请求编码
        apiReq.setRequestNo(order.getReqNo());
        //履约方式
        apiReq.setFulfillmentType("100");
        //履约优先级
        apiReq.setPriority(order.getFulfillmentPriority());
        //发货仓编码（逻辑仓）编码
        apiReq.setLogicShippingWarehouseCode(order.getWareHouseOutCode());
        //销售组织
        apiReq.setSalesOrganizationCode(order.getOrganizationOutCode());
        //送达方
        apiReq.setShipToPartyCode(order.getReceiveAddressCode());
        //售达方
        apiReq.setSoldToPartyCode(order.getCustomerCode());
        //收货仓编码
        apiReq.setLogicReceivingWarehouseCode(order.getReceiveWareHouseOutCode());
        //创建人
        apiReq.setCreator(order.getCreatorName());
        //期望交货日期
        apiReq.setExpectedDeliveryDate(TimeUtil.formatYYYY_MM_dd(order.getCustomerExpectDate()));
        //配送方式编码
        apiReq.setShippingMethodCode(order.getTransportModeCode());
        List<CreateFulfillmentOrderDetailOpenApiDTO> detailList = Lists.newArrayList();
        //明细行，需要处理，找到修改中增加的数量
        Map<String, OrderLine> orderLineMap = orderLineList.stream().collect(Collectors.toMap(OrderLine::getOuterOrderLineId, Function.identity(), (p1, p2) -> p2));
        log.info("buildCreateFulfillmentOrderOpenApiReq#,remainMap={},orderLineMap={}",JSON.toJSONString(remainMap),JSON.toJSONString(orderLineMap));
        sdo.getItems().forEach(item->{
            CreateFulfillmentOrderDetailOpenApiDTO detailOpenApiDTO = new CreateFulfillmentOrderDetailOpenApiDTO();
            if(remainMap.containsKey(item.getAllocateOrderLineId()) && orderLineMap.containsKey(item.getAllocateOrderLineId())){
                OrderLine orderLine = orderLineMap.get(item.getAllocateOrderLineId());
                detailOpenApiDTO.setSourceOrderLineNo(orderLine.getSourceLineNum());
                detailOpenApiDTO.setRefOrderNo(orderLine.getMainOrderBizId());
                detailOpenApiDTO.setRefOrderLineNo(orderLine.getSerialNumber());
                detailOpenApiDTO.setRefOrderCreateTime(TimeUtil.formatYYYY_MM_dd_time(orderLine.getGmtCreate()));
                detailOpenApiDTO.setMaterialCode(orderLine.getScItemOutCode());
                detailOpenApiDTO.setProductionDate(TimeUtil.formatYYYY_MM_dd(orderLine.getProductationTime()));
                detailOpenApiDTO.setSalesUnitCode(orderLine.getSaleUnit());
                String unitConvert = orderLine.getUnitConvert().split("\\.")[0];
                //待出库数量
                Long remain = remainMap.get(item.getAllocateOrderLineId());
                detailOpenApiDTO.setSaleQuantity(String.valueOf(remain));
                //库存单位数量
                BigDecimal divide = BigDecimal.valueOf(remain).divide(BigDecimal.valueOf(Long.valueOf(unitConvert)), 3, BigDecimal.ROUND_FLOOR);
                detailOpenApiDTO.setQuantity(divide.toEngineeringString());
                detailOpenApiDTO.setShippingUnitCode(orderLine.getInventoryUnitCode());
                detailOpenApiDTO.setRemark(orderLine.getRemark());
                detailOpenApiDTO.setBizFeatures(orderLine.getBizFeatures());
                detailList.add(detailOpenApiDTO);
            }
        });
        apiReq.setDetailList(detailList);

        apiReq.setAutoSubmit("1");
        //业态编码
        apiReq.setBusinessType(String.valueOf(order.getBusinessType()));
        //业务单元编码
        apiReq.setBusinessUnitCode(order.getBisUnitOutCode());
        //来源单号
        apiReq.setSourceOrderNo(order.getOrderBizId());
        //业务单据类型
        apiReq.setRefOrderType("101");
        return apiReq;
    }

    private Map<String, String> getFeatures(String features) {
        Map<String, String> map = new HashMap<>();
        String[] split = features.split(";");
        for (int i = 0; i < split.length; i++) {
            String item = split[i];
            String[] keyValue  = item.split(":");
            if(keyValue.length>1){
                String key = keyValue[0];
                String value = keyValue[1];
                map.put(key,value);
            }
        }
        return map;
    }

    private boolean isModifyStock(MnSapIf013SDO sdo, List<OrderLine> result) {
        //明细行map,key = outerOrderLineId value = OrderLine
        Map<String, OrderLine> orderLineMap = result.stream().collect(Collectors.toMap(OrderLine::getOuterOrderLineId, Function.identity(), (p1, p2) -> p2));
        List<MnSapIf013Detail> items = sdo.getItems();
        for (int i = 0; i < items.size(); i++) {
            MnSapIf013Detail item = items.get(i);
            if(orderLineMap.containsKey(item.getAllocateOrderLineId())){
                OrderLine orderLine = orderLineMap.get(item.getAllocateOrderLineId());
                //是否修改库存地址，交货工厂
                if(!Objects.equals(orderLine.getDeliveryFactoryCode(),item.getExt2())
                || !Objects.equals(orderLine.getStockCode(),item.getExt3())){
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isCloseLine(MnSapIf013SDO sdo) {
          return sdo.getItems().stream().anyMatch(it -> StringUtils.isNotBlank(it.getCloseCode()));
    }

    private boolean isModifyAmount(MnSapIf013SDO sdo, List<OrderLine> result) {
        //明细行map,key = outerOrderLineId value = OrderLine
        Map<String, OrderLine> orderLineMap = result.stream().collect(Collectors.toMap(OrderLine::getOuterOrderLineId, Function.identity(), (p1, p2) -> p2));
        List<MnSapIf013Detail> items = sdo.getItems();
        for (int i = 0; i < items.size(); i++) {
            MnSapIf013Detail item = items.get(i);
            if(orderLineMap.containsKey(item.getAllocateOrderLineId())){
                OrderLine orderLine = orderLineMap.get(item.getAllocateOrderLineId());
                //是否修改了数量，sap返回的是携带了三位小数，需要裁切掉
                if(!Objects.equals(orderLine.getQuantity(),Integer.valueOf(item.getQuantity().split("\\.")[0]))){
                    return true;
                }
            }
        }
       return false;
    }

    private MnSapIf015Request generateMnSapIf015Request(MessageHeaderSDO messageHeader, MnSapIf013SDO mnSapIf013SDO, boolean isPilot, List<String> toOtwFactoryCodes) {
        log.info("generateMnSapIf015Request mnSapIf013SDO={}", JSON.toJSONString(mnSapIf013SDO));
        MnSapIf015Request mnSapIf015Request = new MnSapIf015Request();
        MessageHeaderSDO copy = new MessageHeaderSDO();
        BeanUtils.copyProperties(messageHeader, copy);
        mnSapIf015Request.setMessageHeader(copy);
        MnSapIf015SDO mnSapIf015SDO = new MnSapIf015SDO();
        mnSapIf015SDO.setTradeOrderId(mnSapIf013SDO.getAllocateOrderId());
        mnSapIf015SDO.setOutOrderId(mnSapIf013SDO.getOutAllocateOrderId());
        mnSapIf015SDO.setOrderType(mnSapIf013SDO.getOrderType());
        mnSapIf015SDO.setSaleOrganizationCode(mnSapIf013SDO.getSaleOrganizationCode());
        mnSapIf015SDO.setSapChannel(mnSapIf013SDO.getSapChannel());
        mnSapIf015SDO.setProductGroupCode(mnSapIf013SDO.getProductGroupCode());
        mnSapIf015SDO.setCreator(mnSapIf013SDO.getCreator());
        mnSapIf015SDO.setModifier(mnSapIf013SDO.getModifier());
        mnSapIf015SDO.setSaleChannelCode(mnSapIf013SDO.getSaleChannel());
        mnSapIf015SDO.setSaleDepartmentCode(mnSapIf013SDO.getSaleDepartmentCode());
        mnSapIf015SDO.setCreateDate(mnSapIf013SDO.getCreateDate());
        mnSapIf015SDO.setCreateTime(mnSapIf013SDO.getCreateTime());
        mnSapIf015SDO.setGmtModified(mnSapIf013SDO.getModifyDate());
        mnSapIf015SDO.setBeginTime(mnSapIf013SDO.getDocTime());
        mnSapIf015SDO.setSoldPartCode(mnSapIf013SDO.getSoldPartCode());
        mnSapIf015SDO.setDeliveryPartCode(mnSapIf013SDO.getDeliveryPartCode());
        mnSapIf015SDO.setExpectedDeliveryTime(mnSapIf013SDO.getExpectedDeliveryTime());
        mnSapIf015SDO.setRemark(mnSapIf013SDO.getRemark());
        mnSapIf015SDO.setCustomerReferenceNo(mnSapIf013SDO.getCustomerReferenceNo());
        mnSapIf015SDO.setCashCustomerName(mnSapIf013SDO.getCostCenter());
        mnSapIf015SDO.setCreateReason(mnSapIf013SDO.getOrderReason());
        //priceTime 不传
//        mnSapIf015SDO.setPriceTime(mnSapIf013SDO.get);
        mnSapIf015SDO.setShipType(mnSapIf013SDO.getShipType());
        mnSapIf015SDO.setFeatures(mnSapIf013SDO.getFeatures());
        //从sap接口文档上看mnSapIf015SDO跟mnSapIf013SDO的ext和ext1是反着的
        mnSapIf015SDO.setExt(mnSapIf013SDO.getExt1());
        mnSapIf015SDO.setExt1(mnSapIf013SDO.getExt());

        //针对SAP创建订单通过013回调，需要补充的字段,这几个参数不一定会用到
        // 履约优先级
        mnSapIf015SDO.setFulfillmentPriority("1");
        if (isPilot || toOtwFactoryCodes.contains(mnSapIf013SDO.getFactoryCode())) {
            //自动履约
            mnSapIf015SDO.setAutoFulfillment("true");
            //履约方式
            mnSapIf015SDO.setFulfillmentTypeCode("110");
        } else {
            //自动履约
            mnSapIf015SDO.setAutoFulfillment("false");
            //履约方式
            mnSapIf015SDO.setFulfillmentTypeCode("130");
        }
        //订单渠道编码
        mnSapIf015SDO.setOrderChannelCode("500");
        mnSapIf015SDO.setChannelOutCode(mnSapIf013SDO.getSapChannel());
        //业务单元外部编码
        mnSapIf015SDO.setBisUnitOutCode(mnSapIf013SDO.getSaleOrganizationCode());

        List<MnSapIf015Detail> items = new ArrayList<>();
        for (MnSapIf013Detail mnSapIf013Detail : mnSapIf013SDO.getItems()) {
            String quantity = mnSapIf013Detail.getQuantity();
            String subTotalAmount = mnSapIf013Detail.getSubTotalAmount();
            String activityPrice = null;
            if (quantity != null && subTotalAmount != null) {
                // 计算活动单价，保留两位小数后四舍五入
                activityPrice = new BigDecimal(subTotalAmount).divide(new BigDecimal(quantity), 2, RoundingMode.HALF_UP).toString();
            }

            MnSapIf015Detail mnSapIf015Detail = new MnSapIf015Detail();
            mnSapIf015Detail.setOrderLineId(mnSapIf013Detail.getAllocateOrderLineId());
            mnSapIf015Detail.setOutOrderLineId(mnSapIf013Detail.getOutAllocateOrderLineId());
            mnSapIf015Detail.setScItemId(mnSapIf013Detail.getScItemId());
            mnSapIf015Detail.setQuantity(quantity);
            mnSapIf015Detail.setSaleUnit(mnSapIf013Detail.getSaleUnit());
            mnSapIf015Detail.setPrice(mnSapIf013Detail.getPrice());
            mnSapIf015Detail.setSubTotalAmount(subTotalAmount);
            mnSapIf015Detail.setActivityPrice(activityPrice);
//            mnSapIf015Detail.setReturnFlag(mnSapIf013Detail.);
            mnSapIf015Detail.setCloseCode(mnSapIf013Detail.getCloseCode());
            mnSapIf015Detail.setCloseReason(mnSapIf013Detail.getCloseReason());
            mnSapIf015Detail.setRemark(mnSapIf013Detail.getRemarks());
            mnSapIf015Detail.setFeatures(mnSapIf013Detail.getFeatures());
            //工厂编码和库存地点
            mnSapIf015Detail.setFactoryCode(mnSapIf013Detail.getExt2());
            mnSapIf015Detail.setInventoryCode(mnSapIf013Detail.getExt3());
            //生产日期
            mnSapIf015Detail.setExt7(mnSapIf013Detail.getExt());
            mnSapIf015Detail.setConfirmQuantity(mnSapIf013Detail.getConfirmQuantity());
            mnSapIf015Detail.setGiftQuantity(mnSapIf013Detail.getGiftQuantity());
            mnSapIf015Detail.setTaxRate(mnSapIf013Detail.getTaxRate());
            items.add(mnSapIf015Detail);
        }
        mnSapIf015SDO.setItems(items);
        mnSapIf015Request.setData(mnSapIf015SDO);
        log.info("generateMnSapIf015Request result:{}", JSON.toJSONString(mnSapIf015Request));
        return mnSapIf015Request;
    }

    private MnSapCommResponse mnSapCommResponseConverter(MnSapIf013Request mnSapIf013Request,MnSapIf013SDO data ,MnSapCommResponse response ,List<MnSapCommSDO> mnSapCommSDOS) {
        ModifyOrderRequest request = new ModifyOrderRequest();

        MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();

        //根据配置表进行数据拦截过滤
        DataCheckRequest dataCheckRequest = new DataCheckRequest();
        dataCheckRequest.setOrderType(OrderTypeEnum.SALEORDER.getCode());
        dataCheckRequest.setChannelOutCode(data.getSapChannel());
        dataCheckRequest.setOrgOutCode(data.getSaleOrganizationCode());
        dataCheckRequest.setVariable(SapAndCrmFieldDealUtils.toDateString(data.getCreateDate()));
        Result<Boolean> checkResult = interfaceDataSyncConfigQueryService.dataCheck(dataCheckRequest);
        if (checkResult != null && checkResult.getResult() != null && !checkResult.getResult()){
            log.info("interfaceDataSyncConfigQueryService 拦截 "+ data.getOutAllocateOrderId());
            mnSapCommSDO.setStatus("S");
            mnSapCommSDO.setMessage("成功");
            mnSapCommSDOS.add(mnSapCommSDO);
            response.setData(mnSapCommSDOS);
            return success(mnSapIf013Request);
        }

        request.setOrderType(data.getOrderType());
        request.setOutOrderId(data.getOutAllocateOrderId());
        //sap销售组织信息->平台
        List<String> outCodes = new ArrayList<>();
        outCodes.add(data.getSaleOrganizationCode());
        BaselineGetOrganizationByOutCodes2Request byOutCodes2Request = new BaselineGetOrganizationByOutCodes2Request();
        byOutCodes2Request.setOutCodes(outCodes);
        byOutCodes2Request.setStatus(1);
//        Map saleOrgMap = externalSyncSaleOrder$getOrganizationByOutCodes(outCodesRequest);
        BaselineGetOrganizationByOutCodes2Response byOutCodes2Response =  baseDataService.baselineGetOrganizationByOutCodes2(byOutCodes2Request);

//        JSONArray saleJsonArray = JSONObject.parseObject(JSONObject.toJSONString(saleOrgMap)).getJSONArray("result");
        if (byOutCodes2Response == null || CollectionUtils.isEmpty(byOutCodes2Response.getResult())) {
            mnSapCommSDO.setStatus("E");
            mnSapCommSDO.setMessage("销售组织转换失败");
            mnSapCommSDO.setErrCode("OTS-05-001-10-16-049");
            mnSapCommSDOS.add(mnSapCommSDO);
            response.setData(mnSapCommSDOS);
            log.error("MnSapIf015Service.externalSyncSaleOrder error: " + JSON.toJSONString(response));
            return response;
        }

        Map<String,OrganizationSDO> organizationSDOMap = byOutCodes2Response.getResult().stream().collect(Collectors.toMap(OrganizationSDO::getOutCode,org -> org,(k1,k2)->k2));
        if (organizationSDOMap.get(data.getSaleOrganizationCode()) != null) {
            OrganizationSDO organizationSDO = organizationSDOMap.get(data.getSaleOrganizationCode());
            request.setSaleOrganizationCode(organizationSDO.getId());
            request.setSaleOrganizationName(organizationSDO.getName());
        }else {
            mnSapCommSDO.setStatus("E");
            mnSapCommSDO.setMessage("销售组织转换失败");
            mnSapCommSDO.setErrCode("OTS-05-001-10-16-049");
            mnSapCommSDOS.add(mnSapCommSDO);
            response.setData(mnSapCommSDOS);
            log.error("MnSapIf015Service.externalSyncSaleOrder error: " + JSON.toJSONString(response));
            return response;
        }

        //sap业务渠道->平台
        BaselineQueryChannelByPageRequest channelByPageRequest = new BaselineQueryChannelByPageRequest();
        channelByPageRequest.setOutCode(data.getSapChannel());
        Map map = (Map) baseDataService.baselineQueryChannelByPage(channelByPageRequest);
        JSONObject jsonMap = JSONObject.parseObject(JSONObject.toJSONString(map));
        JSONArray jsonArray = jsonMap.getJSONObject("result").getJSONArray("content");
        if (CollectionUtils.isEmpty(jsonArray)) {
            mnSapCommSDO.setStatus("E");
            mnSapCommSDO.setMessage("业务渠道转换失败");
            mnSapCommSDO.setErrCode("999");
            mnSapCommSDOS.add(mnSapCommSDO);
            response.setData(mnSapCommSDOS);
            log.error("MnSapIf013Service.externalUpdateAllocateBySaleOrder error: " + JSON.toJSONString(response));
            return response;
        }
        JSONObject jsonObject1 = jsonArray.getJSONObject(0);
        request.setSapChannel(jsonObject1.getString("channelCode"));
        request.setSapChannelName(jsonObject1.getString("channelName"));

        //sap货品组编码->平台
        QueryScItemGroupRequest scItemGroupRequest = new QueryScItemGroupRequest();
        Result<ScItemGroupResponse> scItemGroup = scItemGroupQueryService.getScItemGroup(scItemGroupRequest);
        if (scItemGroup.getResult() == null) {
            mnSapCommSDO.setStatus("E");
            mnSapCommSDO.setMessage("货品组编码转换失败");
            mnSapCommSDO.setErrCode("999");
            mnSapCommSDOS.add(mnSapCommSDO);
            response.setData(mnSapCommSDOS);
            log.error("MnSapIf013Service.externalUpdateAllocateBySaleOrder error: " + JSON.toJSONString(response));
            return response;
        }
        request.setProductGroupCode(scItemGroup.getResult().getCode());
        request.setProductGroupName(scItemGroup.getResult().getName());

        request.setCreator(data.getCreator());
        request.setModifier(data.getModifier());
        request.setCreateDate(SapAndCrmFieldDealUtils.toDateString(data.getCreateDate()));
        request.setCreateTime(SapAndCrmFieldDealUtils.toDateString(data.getCreateTime()));
        if (!"00000000".equals(data.getModifyDate())) {
            request.setGmtModified(SapAndCrmFieldDealUtils.toDateString(data.getModifyDate()));
        }
        request.setBeginTime(SapAndCrmFieldDealUtils.toDateString(data.getDocTime()));


        //sap客户编码、客户收货地址编码->平台
        PageQueryAddressListRequest pageQueryAddressListRequest = new PageQueryAddressListRequest();
        pageQueryAddressListRequest.setAddressCode(data.getDeliveryPartCode());
        pageQueryAddressListRequest.setCustomerCode(data.getSoldPartCode());
        pageQueryAddressListRequest.setOrgSaleOrganizationCode(request.getSaleOrganizationCode());
        pageQueryAddressListRequest.setChannelCode(request.getSapChannel());
        pageQueryAddressListRequest.setItemGroup(data.getProductGroupCode());

        PageQueryAddressListResponse listResult = otsPlatformEnhanceService.pageQueryAddressList(pageQueryAddressListRequest);
        if (CollectionUtils.isEmpty(listResult.getResult())) {
            mnSapCommSDO.setStatus("E");
            mnSapCommSDO.setMessage("客户编码、收货地址转换失败");
            mnSapCommSDO.setErrCode("999");
            mnSapCommSDOS.add(mnSapCommSDO);
            response.setData(mnSapCommSDOS);
            log.error("MnSapIf013Service.externalUpdateAllocateBySaleOrder error: " + JSON.toJSONString(response));
            return response;
        }
        CustomerAddressSDO customerAddressSDO = listResult.getResult().get(0);
        request.setSoldPartCode(customerAddressSDO.getCustomerCode());
        request.setSoldPartName(customerAddressSDO.getCustomerName());
        request.setDeliveryPartCode(customerAddressSDO.getAddressCode());
        request.setDeliveryPartName(customerAddressSDO.getAddressName());
        request.setContactor(customerAddressSDO.getContactName());
        request.setContactorPhone(customerAddressSDO.getCellphoneNumber());

        request.setSaleDepartmentCode(customerAddressSDO.getOrgSaleDepartmentCode());
        request.setSaleDepartmentName(customerAddressSDO.getOrgSalesDepartmentName());
        request.setSaleChannelCode(customerAddressSDO.getOrgSaleChannelCode());
        request.setSaleChannelName(customerAddressSDO.getOrgSalesChannelName());
        //查询部门名称
        if(StringUtils.isEmpty(customerAddressSDO.getOrgSaleDepartmentCode())){
            log.info("MnSapIf015Service.externalSyncSaleOrder:客户送达方未关联销售部门信息");
        }else {
            IdQueryRequest idQueryRequest = new IdQueryRequest();
            idQueryRequest.setId(customerAddressSDO.getOrgSaleDepartmentCode());
            Result<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>  organizationSDOResult = organizationQueryService.getOrganizationDetail(idQueryRequest);
            if (organizationSDOResult != null && organizationSDOResult.getResult() != null ){
                request.setSaleDepartmentName(organizationSDOResult.getResult().getName());
            }else {
                log.info("MnSapIf015Service.externalSyncSaleOrder:未查询到销售部门 "+ JSON.toJSONString(organizationSDOResult));
            }
        }
        if( StringUtils.isEmpty(customerAddressSDO.getOrgSaleChannelCode())){
            log.info("MnSapIf015Service.externalSyncSaleOrder:客户送达方未关联销售渠道信息");
        }else {
            IdQueryRequest idQueryRequest = new IdQueryRequest();
            idQueryRequest.setId(customerAddressSDO.getOrgSaleChannelCode());
            Result<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>  organizationSDOResult = organizationQueryService.getOrganizationDetail(idQueryRequest);
            if (organizationSDOResult != null && organizationSDOResult.getResult() != null ){
                request.setSaleChannelName(organizationSDOResult.getResult().getName());
            }else {
                log.info("MnSapIf015Service.externalSyncSaleOrder:未查询到销售渠道 "+ JSON.toJSONString(organizationSDOResult));
            }
        }

        request.setExpectedDeliveryTime(SapAndCrmFieldDealUtils.toDateString(data.getExpectedDeliveryTime()));
        request.setShipType(data.getShipType());
        request.setRemark(data.getRemark());
        request.setCustomerReferenceNo(data.getCustomerReferenceNo());
        request.setCashCustomerName(data.getCostCenter());
        request.setCostCenter(data.getCostCenter());
        request.setCreateReason(data.getOrderReason());
        //request.setPriceTime(SapAndCrmFieldDealUtils.toDateString(data.getPriceTime()));
        request.setFeatures(data.getFeatures());

        mnSapCommSDO.setStatus("S");
        mnSapCommSDO.setMessage("成功");


        if (CollectionUtils.isNotEmpty(data.getItems())) {
            List<MnSapCommDetail> mnSapCommDetails = new ArrayList<>();
            List<ModifyOrderLineRequest> orderLineRequests = new ArrayList<>();
            for (MnSapIf013Detail detail : data.getItems()) {
                MnSapCommDetail mnSapCommDetail = new MnSapCommDetail();
                mnSapCommDetail.setItemKey(detail.getItem_key());

                ModifyOrderLineRequest lineRequest = new ModifyOrderLineRequest();
                //lineRequest.setOrderLineId(SapAndCrmFieldDealUtils.generateIdField(detail.getOrderLineId()));
                lineRequest.setOutOrderLineId(SapAndCrmFieldDealUtils.generateIdField(detail.getOutAllocateOrderLineId()));
                //sap货品->平台

//                QueryScItemRequest queryScItemRequest = new QueryScItemRequest();
//                queryScItemRequest.setOuterId(SapAndCrmFieldDealUtils.generateIdField(detail.getScItemId()));
//                Result<List<ScItemSDO>> scItemList = scItemQueryService.pageQueryScItemList(queryScItemRequest);

                SearchScItemRequest searchScItemRequest = new SearchScItemRequest();
                SearchReqDTO searchReqDTO = new SearchReqDTO();
                List<String> list = new ArrayList<>();
                list.add(SapAndCrmFieldDealUtils.generateScItemIdField(detail.getScItemId()));
                searchReqDTO.setOuterIdList(list);
                //2022.06.07 商品如果删除了 也算查到商品
                searchReqDTO.setStatusList(Lists.newArrayList(1,-1));
                searchScItemRequest.setSearchReqDTO(searchReqDTO);
                Result<List<ScItemSDO>> scItemList = baseDataService.searchScItem(searchScItemRequest);

                if (scItemList.isSuccess() && CollectionUtils.isNotEmpty(scItemList.getResult())) {
                    ScItemSDO scItemSDO = scItemList.getResult().get(0);

                    lineRequest.setScItemOutCode(scItemSDO.getOuterId());
                    lineRequest.setScItemName(scItemSDO.getTitle());
                    lineRequest.setScItemId(scItemSDO.getScItemId());
                    Map<String, String> features = scItemSDO.getFeatures();
                    if (MapUtils.isNotEmpty(features)) {
                        String unitName = features.get("unit");
                        String unitCode = features.get("unitName");
                        lineRequest.setCategoryCode(features.get("category"));
                        lineRequest.setCategoryDesc(features.get("categoryDesc"));
                        lineRequest.setCategoryChildCode(features.get("categoryChildCode"));
                        lineRequest.setCategoryChildDesc(features.get("categoryChildDesc"));
                        if (StringUtils.isNotBlank(unitName)) {
                            lineRequest.setInventoryUnit(unitName);
                        }
                        if (StringUtils.isNotBlank(unitCode)) {
                            lineRequest.setInventoryUnitCode(unitCode);
                        }
                    }
                    //todo 接口未取到库存单位名称
//                        build.setInventoryUnitCode(scItemSDO.getUnit());
//                        build.setInventoryUnit(scItemSDO.getUnit());
                    QuerySaleUnitRequest querySaleUnitRequest = QuerySaleUnitRequest.builder().scItemId(scItemSDO.getScItemId()).build();
                    querySaleUnitRequest.setInventoryUnit(lineRequest.getInventoryUnit());
                    querySaleUnitRequest.setInventoryUnitCode(lineRequest.getInventoryUnitCode());
                    querySaleUnitRequest.setUnitConvert("1");
                    Result<List<SelectCombox>> querySaleUnitList = forecastOrderLineQueryService.querySaleUnitList(querySaleUnitRequest);
                    if (querySaleUnitList.isSuccess() && Objects.nonNull(querySaleUnitList.getResult())) {
                        List<SelectCombox> result = querySaleUnitList.getResult();
                        Map<String, SelectCombox> unitMap = new HashMap<>();
                        Nullable.stream(result).forEach(t -> {
                            unitMap.put(t.getValue(), t);
                        });
                        SelectCombox selected = unitMap.get(detail.getSaleUnit());
                        if (selected != null) {
                            lineRequest.setSaleUnitName(selected.getLabel());
                            lineRequest.setUnitConvert(selected.getExt());
                        }

                        SelectCombox inventoryMap = unitMap.get(detail.getSaleUnit());
                        if (inventoryMap != null) {
                            lineRequest.setInventoryUnit(inventoryMap.getLabel());
//                                build.setUnitConvert(inventoryMap.getExt());
                        }
//                            build.setInventoryUnit(map1.get(scItemSDO.getUnit()));
                    }
                }

                if (CollectionUtils.isEmpty(scItemList.getResult())) {
                    log.error("MnSapIf013ServiceImpl_scItemConvertError:{}",detail.getScItemId());
                    List<MnSapCommDetail> commDetails = new ArrayList<>();
                    mnSapCommSDO.setStatus("E");
                    mnSapCommSDO.setMessage("货品编码转换失败");
                    mnSapCommDetail.setStatus("E");
                    mnSapCommDetail.setMessage("货品编码转换失败");
                    commDetails.add(mnSapCommDetail);
                    mnSapCommSDO.setItem(commDetails);
                    mnSapCommSDOS.add(mnSapCommSDO);
                    response.setData(mnSapCommSDOS);
                    log.error("MnSapIf013Service.externalUpdateAllocateBySaleOrder error: " + JSON.toJSONString(response));
                    return response;
                }

                lineRequest.setQuantity(SapAndCrmFieldDealUtils.toInteger(detail.getQuantity()).toString());
                lineRequest.setSaleUnit(detail.getSaleUnit());
                lineRequest.setPrice(extracted(detail.getPrice()));
                lineRequest.setSubTotalAmount(extracted(detail.getSubTotalAmount()));
                lineRequest.setCloseCode(detail.getCloseCode());
                lineRequest.setCloseReason(detail.getCloseReason());


                WmsQueryWarehouseZoneListRequest warehouseZoneListRequest = new WmsQueryWarehouseZoneListRequest();
                warehouseZoneListRequest.setSapFactoryCode(data.getFactoryCode());
                warehouseZoneListRequest.setWarehouseCode(data.getInventoryCode());
                WmsQueryWarehouseZoneListResponse warehouseZoneList = unifiedInventoryService.wmsQueryWarehouseZoneList(warehouseZoneListRequest);
                if (CollectionUtils.isNotEmpty(warehouseZoneList.getResult())) {
                    WarehouseInfo warehouseInfo = warehouseZoneList.getResult().get(0);
                    lineRequest.setWarehouseCode(warehouseInfo.getId());
                    lineRequest.setWarehouseName(warehouseInfo.getName());
                }
                lineRequest.setFactoryCode(data.getFactoryCode());
                lineRequest.setInventoryCode(data.getInventoryCode());


                orderLineRequests.add(lineRequest);

                mnSapCommDetail.setStatus("S");
                mnSapCommDetail.setMessage("成功");
                mnSapCommDetails.add(mnSapCommDetail);
            }
            mnSapCommSDO.setItem(mnSapCommDetails);
            request.setModifyOrderLineRequests(orderLineRequests);

            //查询客户账款
            CreditQueryRequest creditQueryRequest = new CreditQueryRequest();
            creditQueryRequest.setOrganizationCode(request.getSaleOrganizationCode());
            creditQueryRequest.setChannelCode(request.getSapChannel());
            creditQueryRequest.setItemGroupCode(request.getProductGroupCode());
            creditQueryRequest.setCustomerCode(request.getSoldPartCode());
            Result<CreditInfoSDO> result = creditQueryService.queryCreditBalance(creditQueryRequest);
            if (result.getResult() != null) {
                request.setCustomerAccounts(result.getResult().getBalance());
            }
        }
        log.info("request:" + request);
        try {
            request.setFromSys("APP_SAP");
            orderWriteService.modifySaleOrder(request);
        } catch (Exception e) {
            log.error("MnSapIf013 modifySaleOrder :" + e);
            throw new ProcessException("OTS-05-001-10-16-048");
        }

        mnSapCommSDO.setStatus("S");
        mnSapCommSDO.setMessage("成功");
        mnSapCommSDOS.add(mnSapCommSDO);
        response.setData(mnSapCommSDOS);
        log.info("执行结束");
        return response;
    }

    /**
     * 根据map来获取
     * @param map
     * @return
     */
    public static String getCode(Map map){
        JSONObject obj = JSONObject.parseObject(JSONObject.toJSONString(map));
        if (obj != null){
            obj = obj.getJSONObject("result");
            if (obj != null){
                obj = obj.getJSONObject("result");
                if (obj != null){
                    return obj.getString("code");
                }
            }
        }
        return null;
    }
    public static String getWarehouseId(WmsQueryWarehouseZoneListResponse response){
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())){
            WarehouseResponse warehouseResponse = JsonUtil.convert(response.getResult().get(0),
                    WarehouseResponse.class);
            return warehouseResponse.getWarehouseId();
        }
        return null;
    }
    public static String getWarehouseId(Result<List<WarehouseInfoDTO>> result){
        if (result != null && CollectionUtils.isNotEmpty(result.getResult())){
            WarehouseInfoDTO warehouseInfoDTO = result.getResult().get(0);
            return warehouseInfoDTO.getWarehouseId();
        }
        return null;
    }
    public static String getAreaId(Result<List<WarehouseInfoDTO>> result){
        if (result != null && CollectionUtils.isNotEmpty(result.getResult())){
            WarehouseInfoDTO warehouseInfoDTO = result.getResult().get(0);
            return warehouseInfoDTO.getId();
        }
        return null;
    }

    public static String getAreaId(WmsQueryWarehouseZoneListResponse response){
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())){
            WarehouseResponse warehouseResponse = JsonUtil.convert(response.getResult().get(0),
                    WarehouseResponse.class);
            return warehouseResponse.getId();
        }
        return null;
    }

    private String checkMnSapIf013SDO(MnSapIf013SDO sdo) {
        String msg = null;
        if (StringUtils.isBlank(sdo.getOutAllocateOrderId())){
            msg = "outAllocateOrderId不能为空";
        }
        if (StringUtils.isBlank(sdo.getOrderType())){
            msg = "orderType 不能为空";
        }
        if (StringUtils.isBlank(sdo.getSaleOrganizationCode())){
            msg = "saleOrganizationCode 不能为空";
        }
        if (StringUtils.isBlank(sdo.getSapChannel())){
            msg = "sapChannel 不能为空";
        }
        if (StringUtils.isBlank(sdo.getProductGroupCode())){
            msg = "productGroupCode 不能为空";
        }
        if (StringUtils.isBlank(sdo.getSoldPartCode())){
            msg = "soldPartCode 不能为空";
        }
        //说工厂可以不传库存地点
//            if (StringUtils.isBlank(sdo.getInventoryCode())){
//                msg = "inventoryCode 不能为空";
//                break;
//            }
        if (StringUtils.isBlank(sdo.getDeliveryPartCode())){
            msg = "deliveryPartCode 不能为空";
        }
        if (StringUtils.isBlank(sdo.getFactoryCode())){
            msg = "factoryCode 不能为空";
        }
        if (StringUtils.isBlank(sdo.getShipType())){
            //运输方式默认值
            sdo.setShipType("1");
//                msg = "shipType 不能为空";
//                break;
        }
        if (CollectionUtils.isEmpty(sdo.getItems())){
            msg = "items 不能为空";
        }
        //修改时间 格式为20220307111350.3513180 前面年月日时分秒 后面是 0.3513180
        if (StringUtils.isBlank(sdo.getExt())){
            msg = "ext修改时间不能为空";
        }else {
            String[] split = sdo.getExt().split("\\.");
            if (split.length != 2){
                msg = "ext修改时间 格式错误";
            }
        }

        for (MnSapIf013Detail detail : sdo.getItems()){
            if (StringUtils.isBlank(detail.getOutAllocateOrderLineId())){
                msg = "outAllocateOrderLineId 不能为空";
            }
            if (StringUtils.isBlank(detail.getScItemId())){
                msg = "scItemId 不能为空";
            }
            if (StringUtils.isBlank(detail.getQuantity())){
                msg = "quantity 不能为空";
            }
//                if (StringUtils.isBlank(detail.getConfirmQuantity())){
//                    return ResponseUtil.fail(request,"confirmQuantity 不能为空");
//                }
//                if (StringUtils.isBlank(detail.getPrice())){
//                    return ResponseUtil.fail(request,"price 不能为空");
//                }
            if (StringUtils.isBlank(detail.getSaleUnit())){
                msg = "unit 不能为空";
            }
            if (StringUtils.isNotBlank(detail.getCloseCode()) || StringUtils.isNotBlank(detail.getCloseReason())){
                if (StringUtils.isNotBlank(detail.getQuantity())){
                    BigDecimal decimal = new BigDecimal(detail.getQuantity().trim());
                    if (decimal.intValue() <= 0){
                        msg = "非关闭情况下数量不能小于等于0";
                    }
                }
            }
//                if (StringUtils.isBlank(detail.getCloseCode())){
//                    return ResponseUtil.fail(request,"isClosed 不能为空");
//                }
        }
        //判断是否有重复的物流
        List<String> collect = sdo.getItems().stream().map(x -> {
//                return SapAndCrmFieldDealUtils.generateIdField(x.getScItemId());
            return subStringScItmCode(x.getScItemId());
        }).distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect)){
            msg = "有效items不能为空";
        }
        //物料 去0后不能重复 2022.04.25 去掉物料编码不能重复的校验 如果是分子公司的校验放在后面
//            if (collect.size() < sdo.getItems().size()){
//                return ResponseUtil.fail(request,"物料编码不能重复");
//            }
        return msg;

    }

    public static MnSapCommResponse check(MnSapIf013Request request){
        if (CollectionUtils.isEmpty(request.getData()))return ResponseUtil.fail(request,"传递的调拨单参数列表为空");
        String msg = null;
        for (MnSapIf013SDO sdo : request.getData()) {
            if (StringUtils.isBlank(sdo.getOutAllocateOrderId())){
                msg = "outAllocateOrderId不能为空";
                break;
            }
            if (StringUtils.isBlank(sdo.getOrderType())){
                msg = "orderType 不能为空";
                break;
            }
            if (StringUtils.isBlank(sdo.getSaleOrganizationCode())){
                msg = "saleOrganizationCode 不能为空";
            }
            if (StringUtils.isBlank(sdo.getSapChannel())){
                msg = "sapChannel 不能为空";
                break;
            }
            if (StringUtils.isBlank(sdo.getProductGroupCode())){
                msg = "productGroupCode 不能为空";
                break;
            }
            if (StringUtils.isBlank(sdo.getSoldPartCode())){
                msg = "soldPartCode 不能为空";
                break;
            }
            //说工厂可以不传库存地点
//            if (StringUtils.isBlank(sdo.getInventoryCode())){
//                msg = "inventoryCode 不能为空";
//                break;
//            }
            if (StringUtils.isBlank(sdo.getDeliveryPartCode())){
                msg = "deliveryPartCode 不能为空";
                break;
            }
            if (StringUtils.isBlank(sdo.getFactoryCode())){
                msg = "factoryCode 不能为空";
                break;
            }
            if (StringUtils.isBlank(sdo.getShipType())){
                //运输方式默认值
                sdo.setShipType("1");
//                msg = "shipType 不能为空";
//                break;
            }
            if (CollectionUtils.isEmpty(sdo.getItems())){
                msg = "items 不能为空";
                break;
            }
            //修改时间 格式为20220307111350.3513180 前面年月日时分秒 后面是 0.3513180
            if (StringUtils.isBlank(sdo.getExt())){
                msg = "ext修改时间不能为空";
                break;
            }else {
                String[] split = sdo.getExt().split("\\.");
                if (split.length != 2){
                    msg = "ext修改时间 格式错误";
                    break;
                }
            }

            for (MnSapIf013Detail detail : sdo.getItems()){
                if (StringUtils.isBlank(detail.getOutAllocateOrderLineId())){
                    return ResponseUtil.fail(request,"outAllocateOrderLineId 不能为空");
                }
                if (StringUtils.isBlank(detail.getScItemId())){
                    return ResponseUtil.fail(request,"scItemId 不能为空");
                }
                if (StringUtils.isBlank(detail.getQuantity())){
                    return ResponseUtil.fail(request,"quantity 不能为空");
                }
//                if (StringUtils.isBlank(detail.getConfirmQuantity())){
//                    return ResponseUtil.fail(request,"confirmQuantity 不能为空");
//                }
//                if (StringUtils.isBlank(detail.getPrice())){
//                    return ResponseUtil.fail(request,"price 不能为空");
//                }
                if (StringUtils.isBlank(detail.getSaleUnit())){
                    return ResponseUtil.fail(request,"unit 不能为空");
                }
                if (StringUtils.isNotBlank(detail.getCloseCode()) || StringUtils.isNotBlank(detail.getCloseReason())){
                    if (StringUtils.isNotBlank(detail.getQuantity())){
                        BigDecimal decimal = new BigDecimal(detail.getQuantity().trim());
                        if (decimal.intValue() <= 0){
                            return ResponseUtil.fail(request,"非关闭情况下数量不能小于等于0");
                        }
                    }
                }
//                if (StringUtils.isBlank(detail.getCloseCode())){
//                    return ResponseUtil.fail(request,"isClosed 不能为空");
//                }
            }
            //判断是否有重复的物流
            List<String> collect = sdo.getItems().stream().map(x -> {
//                return SapAndCrmFieldDealUtils.generateIdField(x.getScItemId());
                return subStringScItmCode(x.getScItemId());
            }).distinct().collect(Collectors.toList());
            if (CollectionUtils.isEmpty(collect)){
                return ResponseUtil.fail(request,"有效items不能为空");
            }
            //物料 去0后不能重复 2022.04.25 去掉物料编码不能重复的校验 如果是分子公司的校验放在后面
//            if (collect.size() < sdo.getItems().size()){
//                return ResponseUtil.fail(request,"物料编码不能重复");
//            }
        }
        if (msg != null){
            return ResponseUtil.fail(request,msg);
        }
        return null;
    }


    public static String getWarehouseId(SearchCargoZoneListResponse response){
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())){
            WarehouseInfo warehouseInfo = JsonUtil.convert(response.getResult().get(0), WarehouseInfo.class);
            return warehouseInfo.getId();
        }
        return null;
    }
    /**
     * 截取scItemCode 固定长度为12
     * @param str
     * @return
     */
    public static String subStringScItmCode(String str){
        if (StringUtils.isBlank(str)){
            return null;
        }
        if (str.length()>12){
            return str.substring(str.length()-12);
        }
        return str;
    }

    public  String getOrgCode(String orgId){
        //发货收货仓的组织id name
        BaselineGetOrganizationByIdsRequest r = new BaselineGetOrganizationByIdsRequest();
        if (StringUtils.isNotBlank(orgId)){
            r.setIds(Lists.newArrayList(orgId));
            Object obj = baseDataService.baselineGetOrganizationByIds(r);
            JSONObject o = JSONObject.parseObject(JSONObject.toJSONString(obj));
            if (o != null){
                JSONArray array = o.getJSONArray("result");
                if (array != null && array.size() > 0){
                    JSONObject j = array.getJSONObject(0).getJSONObject("organizationSDO");
                    if (j != null){
                        return j.getString("code");
                    }
                }
            }
        }
        return null;
    }
    /**
     * 价格字段放大100倍防止精度
     * @param s
     * @return
     */
    private static String extracted(String s) {
        if (StringUtils.isBlank(s)) {
            return null;
        }
        BigDecimal val = new BigDecimal(s.trim());
        val = val.multiply(new BigDecimal(100)).setScale(0, RoundingMode.DOWN);
        return val.toString();
    }

    public static MnSapCommResponse success(MnSapIf013Request request){
        MnSapCommResponse response = new MnSapCommResponse();
        MessageHeaderSDO messageHeaderSDO = request.getMessageHeader();
        if (CollectionUtils.isNotEmpty(request.getData())){
            List<MnSapCommSDO> mnSapCommSDOS = Lists.newArrayList();
            for (MnSapIf013SDO mnSapIf013SDO : request.getData()) {
                MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                mnSapCommSDO.setHeaderKey(mnSapIf013SDO.getHeaderKey());
                mnSapCommSDO.setExtId(null);
                mnSapCommSDO.setMessage(MnSAPStatus.SUCCESS.getMsg());
                mnSapCommSDO.setStatus(MnSAPStatus.SUCCESS.getCode());
                List<MnSapCommDetail> mnSapCommDetails = Lists.newArrayList();
                if (CollectionUtils.isNotEmpty(mnSapIf013SDO.getItems())) {
                    mnSapCommDetails = mnSapIf013SDO.getItems().stream().map(m -> {
                        MnSapCommDetail mnSapCommDetail = new MnSapCommDetail();
                        mnSapCommDetail.setItemKey(m.getItem_key());
                        mnSapCommDetail.setStatus(MnSAPStatus.SUCCESS.getCode());
                        mnSapCommDetail.setMessage(MnSAPStatus.SUCCESS.getMsg());
                        return mnSapCommDetail;
                    }).collect(Collectors.toList());
                    mnSapCommSDO.setItem(mnSapCommDetails);
                }
                mnSapCommSDOS.add(mnSapCommSDO);
            }
            response.setData(mnSapCommSDOS);
        }
        if (Objects.nonNull(messageHeaderSDO)) {
            response.setInterfacePath(messageHeaderSDO.getInterfacePath());
            response.setMessageId(messageHeaderSDO.getMessageId());
        }
        return response;
    }

    public  String getOrgOutCodeBySoldPartCode(String soldPartCode){
        if (StringUtils.isBlank(soldPartCode)){
            return getOrgOutCodeByHeadquartersCode("6000");
        }
        String outSoldPartCode = getOrgOutCodeByHeadquartersCode(soldPartCode);
        if (StringUtils.isBlank(outSoldPartCode)){
            return getOrgOutCodeByHeadquartersCode("6000");
        }else{
            return outSoldPartCode;
        }
    }
    private String getOrgOutCodeByHeadquartersCode(String soldPartCode){
        BaselineGetOrganizationByCodes2Request baselineGetOrganizationByCodes2Request = new BaselineGetOrganizationByCodes2Request();
        baselineGetOrganizationByCodes2Request.setIds(Lists.newArrayList(soldPartCode));
        BaselineGetOrganizationByCodes2Response baselineGetOrganizationByCodes2Response = baseDataService.baselineGetOrganizationByCodes2(baselineGetOrganizationByCodes2Request);
        if (Objects.nonNull(baselineGetOrganizationByCodes2Response)&&CollectionUtils.isNotEmpty(baselineGetOrganizationByCodes2Response.getResult())){
            String outcode = baselineGetOrganizationByCodes2Response.getResult().get(0).getId();
            if (org.apache.commons.lang.StringUtils.isNotBlank(outcode)){
                return outcode;
            }
        }
        return "";
    }

    private static String getOrgId(Map obj){
        JSONObject o = JSONObject.parseObject(JSONObject.toJSONString(obj));
        if (o != null){
            JSONArray array = o.getJSONArray("result");
            if (array != null && array.size() > 0){
                JSONObject j = array.getJSONObject(0).getJSONObject("organizationSDO");
                AllocateOrderDetailBatchGetOrgResponse r =
                        JsonUtil.convert(j,AllocateOrderDetailBatchGetOrgResponse.class);
                if (r != null){
                    return r.getId();
                }
            }
        }
        return null;
    }

    /**
     * 保存sap重试记录
     *
     */
    public void saveSapRetry(MnSapIf013Request request,MnSapIf013SDO sdo, String code){
        try{
            if (request == null ||(StringUtils.isNotBlank(code) && code.startsWith("STO"))){
                return;
            }
            SapRetrySaveRequest sapRetrySaveRequest = new SapRetrySaveRequest();
            String requestJson = JSON.toJSONString(request);
            sapRetrySaveRequest.setParam(requestJson);
            sapRetrySaveRequest.setMsg(code);
            sapRetrySaveRequest.setMessageId(request.getMessageHeader().getMessageId());
            //请求时间戳
            sapRetrySaveRequest.setRequestTime(sdo.getExt());
            sapRetrySaveRequest.setApiCode(SapApiCode.SAP013.getValue());
            sapRetrySaveRequest.setOutKey(sdo.getOutAllocateOrderId());
            sapRetrySaveRequest.setStatus(RetryStatus.FAIL.getValue());
            sapRetryWriteService.save(sapRetrySaveRequest);
        }catch (Throwable e){
            log.error("sapRetrySaveError",e);
        }
    }
    //013走预报销售逻辑的销售单
    void isNeedSaveRetry(MnSapCommResponse mnSapCommResponse,MnSapIf013Request mnSapIf013Request){
        try{
            if (Objects.nonNull(mnSapCommResponse) && CollectionUtils.isNotEmpty(mnSapCommResponse.getData())
                    && Objects.nonNull(mnSapCommResponse.getData().get(0))){
                if (!"S".equalsIgnoreCase(mnSapCommResponse.getData().get(0).getStatus())){
                    saveSapRetry(mnSapIf013Request,mnSapIf013Request.getData().get(0),
                            mnSapCommResponse.getData().get(0).getMessage());
                }
            }
        }catch (Throwable e){
            log.error("sapRetrySaveError",e);
        }
    }

    //重试004先于调拨单的物料凭证
    private void retry(String outAllocateOrderId,boolean canRetry){
        if (!canRetry){
            return;
        }
        MaterialSyncRetryLoadListRequest materialSyncRetryLoadListRequest = new MaterialSyncRetryLoadListRequest();
        materialSyncRetryLoadListRequest.setOutOrderId(outAllocateOrderId);
        materialSyncRetryLoadListRequest.setStatus(0);
        materialSyncRetryLoadListRequest.setLimit(MAX_PAGE_SIZE);
        Result<List<MaterialSyncRetry>> listResult = materialSyncRetryService.loadList(materialSyncRetryLoadListRequest);
        if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
            for (MaterialSyncRetry materialSyncRetry : listResult.getResult()) {
                try {
                    MnSapIf004Request mnSapIf004Request = JSON.parseObject(materialSyncRetry.getRequestParams(),MnSapIf004Request.class);
                    mnSapIf004V2Service.externalSyncMaterial(mnSapIf004Request);
                }catch (Throwable e){
                    log.error("MnSapIf013ServiceImpl_retry",e);
                    log.error("MnSapIf013ServiceImpl_retry,request:{},004:{}",JSON.toJSONString(outAllocateOrderId),JSON.toJSONString(listResult.getResult()));
                }
                continue;
            }
        }
    }

}
